MyBatis 通过泛型化 BaseTypeHandler<T> 配合 Jackson 或 Fastjson2 实现 JSON 字段精准双向转换,需显式指定 typeHandler、适配数据库 JDBC 类型,并为泛型集合定制处理器以避免类型擦除问题。

MyBatis 通过自定义 TypeHandler 处理复杂 JSON 字段,核心是让 Java 对象与数据库中的 JSON 字符串自动双向转换,避免在业务代码里反复调用 JSON.toJSONString() 或 JSON.parseObject()。关键不在“能不能”,而在于“怎么写得稳、用得准、泛型不翻车”。
明确目标类型,选对基类和序列化工具
处理复杂结构(如 List<OrderItem>、嵌套对象、含泛型的 Map)时,不能直接继承 BaseTypeHandler<Object>——它会丢失类型信息,反序列化后变成 LinkedHashMap,强转极易报错。
- 优先用
BaseTypeHandler<T>+ 构造器传入具体 Class,比如new JsonTypeHandler<>(UserPreference.class) - 序列化工具推荐 Jackson(稳定、泛型支持好),避免 Fastjson 2.x 以下版本对泛型擦除处理不严谨的问题
- 若项目已统一用 Alibaba Fastjson2,可继承
AbstractJsonTypeHandler<T>(MyBatis-Plus 提供),重写parse和toJson即可
正确注册并绑定到字段
TypeHandler 必须被 MyBatis 明确识别并应用到对应字段,否则形同虚设。
- 实体类中用
@TableField(typeHandler = JsonTypeHandler.class)(MyBatis-Plus)或@Result(typeHandler = ...)(原生 MyBatis) - XML 映射文件中,
<result>或<parameter>标签必须显式指定typeHandler全限定名,例如:<result property="config" column="config" typeHandler="com.example.JsonTypeHandler"/> - 全局注册(可选):在
mybatis-config.xml中声明,适用于多处复用且类型固定的情况
适配不同数据库的 JDBC 类型
MySQL 的 JSON 字段本质仍是字符串(JDBC Type VARCHAR),但 PostgreSQL 的 json / jsonb 类型需用 OTHER 或专用 PGobject。
立即学习“Java免费学习笔记(深入)”;
- MySQL 场景:
setNonNullParameter直接ps.setString(...);getNullableResult直接rs.getString(...) - PostgreSQL 场景:写入时需 new
PGobject("json", jsonStr)并ps.setObject(...);读取时先rs.getObject(...)再转型为PGobject,再取其getValue() - 别忽略
jdbcType参数:在 XML 中手动指定jdbcType="OTHER"可避免类型推断错误
泛型集合字段要单独封装处理器
像 List<Tag> 这类字段,通用 JsonTypeHandler<T> 无法自动推导泛型实际类型——Java 运行时已擦除。
- 方案一:为每种集合定义专用处理器,如
TagListTypeHandler extends BaseTypeHandler<List<Tag>>,在parse中硬编码objectMapper.readValue(json, new TypeReference<List<Tag>>() {}) - 方案二:使用工厂模式,在构造器传入
TypeReference实例,提升复用性 - 切忌在
getNullableResult里用objectMapper.convertValue(..., List.class)——它不保留泛型信息,结果仍是List<LinkedHashMap>


















