You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot+MyBatis对接PostgreSQL jsonb字段报错的解决方法

Spring Boot + MyBatis 处理PostgreSQL jsonb字段的正确姿势

你遇到的错误核心原因是:数据库tags字段已改为jsonb类型,但MyBatis默认将字符串参数以varchar类型传入,PostgreSQL不允许这种隐式类型转换,因此抛出类型不匹配的报错。以下是几种可行的解决方式:

方案一:SQL语句中显式转换(快速临时解决)

直接在Mapper XML的SQL语句里,给tags参数添加PostgreSQL的类型转换语法,把传入的字符串转为jsonb:

<update id="updateByPrimaryKeySelective" parameterType="com.dolphin.soa.post.entity.RssSubSource">
  UPDATE rss_sub_source 
  SET 
    <!-- 其他字段省略 -->
    tags = #{tags}::jsonb,
    <!-- 其他字段省略 -->
  WHERE id = #{id}
</update>

这种写法兼容tags为null的场景,PostgreSQL会自动将null转为jsonb类型的null。

方案二:自定义TypeHandler(优雅持久化方案)

通过自定义MyBatis类型处理器,实现Java对象与PostgreSQL jsonb类型的自动转换,无需每次写SQL都手动转换。

  1. 实体类字段定义
    实体类的tags字段可以定义为String、Map<String, Object>或自定义POJO:

    public class RssSubSource {
        // 其他字段省略
        private String tags; // 或 private Map<String, Object> tags;
        // getter/setter
    }
    
  2. 编写自定义TypeHandler

    import org.apache.ibatis.type.BaseTypeHandler;
    import org.apache.ibatis.type.JdbcType;
    import org.postgresql.util.PGobject;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import java.sql.CallableStatement;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    
    public class JsonbTypeHandler extends BaseTypeHandler<Object> {
        private static final PGobject JSONB_OBJECT = new PGobject();
        private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
    
        @Override
        public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException {
            JSONB_OBJECT.setType("jsonb");
            // 如果是Map或POJO,转成JSON字符串;如果是String直接用
            JSONB_OBJECT.setValue(OBJECT_MAPPER.writeValueAsString(parameter));
            ps.setObject(i, JSONB_OBJECT);
        }
    
        @Override
        public Object getNullableResult(ResultSet rs, String columnName) throws SQLException {
            String json = rs.getString(columnName);
            try {
                // 根据实体类字段类型选择转换方式,这里以Map为例
                return OBJECT_MAPPER.readValue(json, Map.class);
                // 如果是String直接return json;
            } catch (Exception e) {
                throw new SQLException("解析jsonb字段失败", e);
            }
        }
    
        @Override
        public Object getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
            return getNullableResult(rs, rs.getMetaData().getColumnName(columnIndex));
        }
    
        @Override
        public Object getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
            String json = cs.getString(columnIndex);
            try {
                return OBJECT_MAPPER.readValue(json, Map.class);
            } catch (Exception e) {
                throw new SQLException("解析jsonb字段失败", e);
            }
        }
    }
    
  3. 注册TypeHandler

    • 方式一:在Mapper XML中指定单个字段使用该处理器:
      <update id="updateByPrimaryKeySelective" parameterType="com.dolphin.soa.post.entity.RssSubSource">
        UPDATE rss_sub_source 
        SET 
          <!-- 其他字段省略 -->
          tags = #{tags, typeHandler=com.dolphin.soa.post.handler.JsonbTypeHandler},
          <!-- 其他字段省略 -->
        WHERE id = #{id}
      </update>
      
    • 方式二:全局注册,让所有匹配类型的字段自动使用该处理器(Spring Boot可在配置文件中指定):
      mybatis:
        type-handlers-package: com.dolphin.soa.post.handler
      

方案三:MyBatis-Plus内置支持(若项目使用MyBatis-Plus)

如果项目依赖了MyBatis-Plus,直接利用其内置的JacksonTypeHandler即可实现自动转换:

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
import java.util.Map;

public class RssSubSource {
    // 其他字段省略
    @TableField(typeHandler = JacksonTypeHandler.class)
    private Map<String, Object> tags;
    // 若用自定义POJO,直接替换Map为POJO类即可
    // @TableField(typeHandler = JacksonTypeHandler.class)
    // private TagsDTO tags;
    // getter/setter
}

MyBatis-Plus会自动完成Java对象与jsonb类型的双向转换,无需额外编写SQL或处理器。

内容的提问来源于stack exchange,提问作者Dolphin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 20:57:17