springboot项目中切数据库(mysql-> pg)带来的适配问题:typeHandler,在jdbc中加个参数stringtype=unspecified就行

请先滑到下面,看第7部分,否则走弯路。

一、数据表中有一张表,名为role_permission,DDL如下:

CREATE TABLE "public"."role_permission" (
  "role_id" varchar(64) COLLATE "pg_catalog"."default" NOT NULL,
  "permissions" json,
  "create_time" timestamp(6) DEFAULT CURRENT_TIMESTAMP,
  "update_time" timestamp(6) DEFAULT CURRENT_TIMESTAMP,
  CONSTRAINT "role_permission_pkey" PRIMARY KEY ("role_id")
);

ALTER TABLE "public"."role_permission"  OWNER TO "postgres";
这里可以看到是用的pg数据库;

二、定义entity中的数据表对象;

@TableName(value = "role_permission", autoResultMap = true)
public class RolePermission implements Serializable {

    @Serial
    private static final long serialVersionUID = 1L;

    @TableId(value = "role_id", type = IdType.ASSIGN_UUID)
    private String roleId;

    @TableField(value = "permissions", typeHandler = CeGrantedAuthorityListTypeHandler.class)
    private List<CeGrantedAuthority> permissions;
}
这里省略了创建时间和修改时间字段等,重点是要讨论permissions字段;

三、service层中保存数据;

List<CeGrantedAuthority> permissions = authorities.values().stream().flatMap(Collection::stream).collect(Collectors.toList());
     RolePermission rolePermission = new RolePermission()
                .setRoleId(roleId)
                .setPermissions(permissions);
     this.saveOrUpdate(rolePermission);
以上写法,在mysql数据库中可以正常写入,但是在pg数据库是不行的,会报错,其实是pg数据库对json字段类型会进行强校验,所有只有自己复写saveOrUpdate方法;

四、mapper中定义接口及xml实现;

public interface RolePermissionMapper extends BaseMapper<RolePermission> {
    boolean saveOrUpdate(RolePermission rolePermission);
}

重点是以下的xml实现,重点关注红色部分吧,我调了好久,才成功:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.fit2cloud.dao.mapper.RolePermissionMapper">
        <insert id="saveOrUpdate" parameterType="com.fit2cloud.base.entity.RolePermission">
            INSERT INTO "role_permission" (role_id, permissions)
            VALUES (#{roleId,jdbcType=VARCHAR}, to_json(#{permissions, jdbcType=VARCHAR, typeHandler=com.fit2cloud.common.utils.CeGrantedAuthorityListTypeHandler}))
            ON CONFLICT (role_id)
                DO UPDATE SET
                   permissions =  to_json(EXCLUDED.permissions);
        </insert>
</mapper>

五、修改service中的调用

注释掉this.saveOrUpdate(rolePermission);
添加如下调用:

baseMapper.saveOrUpdate(rolePermission);

至此解决

环境:springboot3.1.0

        mybatis-plus:3.5.3.1
        postgsql  13.5

六、修改后带来的一些问题

   mysql切pg数据库后,使用to_json会在json字符串前后加上双引号,并对其中的双引号进行转义,因此在回显时需要先处理一下,这部分也就是在CeGrantedAuthorityListTypeHandler进行修改(以下代码中红色部分就是我加的,能起作用,但是感觉不优雅,欢迎给出更好的解决方案)。

@Override
protected Object parse(String json) {
    try {
        if ( json.startsWith("\"") && json.endsWith("\"") ) {
            json = json.substring(1, json.length() - 1);
        }
        json = json.replace("\\\"","\"");
        JavaType javaType = getObjectMapper().getTypeFactory().constructParametricType(List.class, CeGrantedAuthority.class);
        return getObjectMapper().readValue(json, javaType);
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

七、以上的工作都是徒劳,其实改个配置就好了

jdbc:postgresql://{ip:port}/database?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=false&
stringtype=unspecified

加上 stringtype=unspecified  这个参数,根本就不再需要to_json这样繁琐的操作了,反向解析也省了。

没办法,刚写不到3周java,肯定是要走弯路的。。。

  • 7
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

扬子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值