MyBatis-Plus JSON类型处理器详解

在数据库设计中,我们经常需要将复杂的Java对象(如MapList、自定义POJO等)以JSON格式存储到数据库的某个字段中(如MySQL的JSON类型字段、PostgreSQL的jsonb字段等)。MyBatis-Plus 提供了 ​JSON类型处理器(TypeHandler)​​ 来实现 Java 对象与数据库 JSON 字段之间的自动转换,避免手动编写序列化/反序列化代码。

图片[1]_MyBatis-Plus JSON类型处理器详解_知途无界

一、核心作用

JSON类型处理器的主要功能是:
在 Java 对象(如 Map<String, Object>List<T>、自定义类等)与数据库的 JSON 字符串(或数据库原生 JSON 类型字段)之间自动完成序列化(Java→JSON字符串)和反序列化(JSON字符串→Java对象)。​


二、MyBatis-Plus 内置的 JSON 类型处理器

MyBatis-Plus 基于 MyBatis 的类型处理器体系,默认提供了对常见 JSON 库(如 Jackson、Gson)的支持,常见的处理器包括:

处理器类适用场景依赖的 JSON 库
JacksonTypeHandler处理任意 Java 对象(如 POJO、Map、List)与 JSON 的转换Jackson (com.fasterxml.jackson)
GsonTypeHandler同上,基于 Gson 实现Gson (com.google.code.gson)
FastjsonTypeHandler(非官方,需自行实现)基于 Fastjson(不推荐,官方未内置)Fastjson

注意​:MyBatis-Plus ​默认没有直接内置所有 JSON 处理器,但 MyBatis 原生提供了 JacksonTypeHandlerGsonTypeHandler(需手动配置或依赖对应库)。MyBatis-Plus 在部分场景下会简化其使用方式。


三、使用步骤(以 Jackson 为例)

1. 添加依赖

确保项目中引入了 ​Jackson​(MyBatis-Plus 默认依赖可能已包含,若无则手动添加):

<!-- MyBatis-Plus 依赖(通常已包含基础功能) -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>最新版本</version>
</dependency>

<!-- Jackson 依赖(若项目中未引入) -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.13.0</version> <!-- 根据实际情况调整版本 -->
</dependency>

2. 定义实体类字段

假设我们有一个 User 实体,其中有一个字段 tags(类型为 List<String>)需要存储为数据库的 JSON 字段(如 MySQL 的 VARCHARJSON 类型):

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import java.util.List;

@TableName("user") // 对应数据库表名
public class User {
    private Long id;
    private String name;

    // 关键:通过 @TableField 指定类型处理器
    @TableField(typeHandler = com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler.class)
    private List<String> tags; // 需要存储为 JSON 的字段

    // getter/setter 省略...
}

注意​:

  • 如果使用 ​MyBatis 原生​ 的 JacksonTypeHandler,其完整类名是 com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler(MyBatis-Plus 封装)或 org.apache.ibatis.type.JacksonTypeHandler(MyBatis 原生,需确认版本)。
  • MyBatis-Plus 3.x+ 通常直接支持,无需显式指定 typeHandler(见下文简化用法)。

3. 简化用法(MyBatis-Plus 3.x+ 推荐)

MyBatis-Plus 3.x 及以上版本对 JSON 类型处理器进行了优化,​如果数据库字段类型是 JSON(如 MySQL 的 JSON 类型)或字符串类型(如 VARCHAR),且字段类型是 MapList、自定义 POJO 等,MyBatis-Plus 会自动使用内置的 JSON 处理器,无需手动指定 @TableField(typeHandler=...)

示例(自动处理):

@TableName("user")
public class User {
    private Long id;
    private String name;

    // 直接声明为 List<String>,MyBatis-Plus 会自动使用 JSON 处理器
    private List<String> tags; 

    // 或者自定义 POJO
    private Map<String, Object> extraInfo; 

    // getter/setter...
}

条件​:

  • 数据库字段类型需为 ​JSON 类型(如 MySQL 5.7+ 的 JSON 类型、PostgreSQL 的 jsonb)​​ 或 ​字符串类型(如 VARCHARTEXT)​
  • MyBatis-Plus 会通过自动配置的 JacksonTypeHandlerGsonTypeHandler(根据项目依赖)完成转换。

4. 自定义 JSON 处理器(可选)

如果默认处理器不满足需求(如需要特殊序列化逻辑),可以自定义类型处理器并继承 BaseTypeHandler 或直接使用 Jackson/Gson API。

示例(自定义 Jackson 处理器):

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

// 自定义类型处理器(处理 UserConfig 类与 JSON 的转换)
public class UserConfigTypeHandler extends BaseTypeHandler<UserConfig> {
    private static final ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, UserConfig parameter, JdbcType jdbcType) throws SQLException {
        try {
            String json = objectMapper.writeValueAsString(parameter); // 序列化为 JSON 字符串
            ps.setString(i, json);
        } catch (Exception e) {
            throw new SQLException("序列化 UserConfig 失败", e);
        }
    }

    @Override
    public UserConfig getNullableResult(ResultSet rs, String columnName) throws SQLException {
        String json = rs.getString(columnName);
        return parseJson(json); // 反序列化
    }

    // 其他重载方法(getNullableResult)类似...
    private UserConfig parseJson(String json) throws SQLException {
        if (json == null || json.isEmpty()) return null;
        try {
            return objectMapper.readValue(json, UserConfig.class);
        } catch (Exception e) {
            throw new SQLException("反序列化 UserConfig 失败", e);
        }
    }
}

然后在实体类字段上指定该处理器:

@TableField(typeHandler = UserConfigTypeHandler.class)
private UserConfig config; // 自定义 POJO 字段

四、数据库字段类型建议

  • MySQL​:推荐使用 JSON 类型(MySQL 5.7+ 支持),或 VARCHAR/TEXT(兼容旧版本)。
  • PostgreSQL​:推荐使用 jsonb 类型(支持高效索引和查询)。
  • Oracle​:可使用 CLOBVARCHAR2(存储 JSON 字符串)。

注意​:如果数据库字段类型是 JSON(如 MySQL),数据库本身会校验 JSON 格式合法性;如果是字符串类型(如 VARCHAR),需依赖应用层保证格式正确。


五、常见问题解决

1. 报错:找不到类型处理器

原因​:未正确引入 Jackson/Gson 依赖,或未指定 typeHandler(旧版本可能需要手动指定)。
解决​:

  • 检查依赖:确保引入了 jackson-databind(或 gson)。
  • 显式指定处理器(MyBatis-Plus 3.x 之前可能需要): @TableField(typeHandler = JacksonTypeHandler.class) private List<String> tags;

2. JSON 字段与 Java 类型不匹配

原因​:数据库中的 JSON 数据结构与 Java 字段类型不一致(如数据库存的是 {"key":"value"},但 Java 字段声明为 List<String>)。
解决​:确保 Java 字段类型与 JSON 数据结构匹配(如 JSON 是对象则用 Map<String, Object> 或自定义 POJO,是数组则用 List<T>)。

3. 序列化/反序列化失败

原因​:Java 对象包含无法序列化的字段(如循环引用、非序列化类)。
解决​:

  • 使用 @JsonIgnore 忽略敏感字段(Jackson)。
  • 确保自定义 POJO 有无参构造方法(反序列化必需)。

六、总结

场景解决方案
存储 List/Map/自定义 POJO 到 JSON 字段直接声明字段类型(如 List<String>),MyBatis-Plus 3.x+ 自动处理;或手动指定 @TableField(typeHandler=JacksonTypeHandler.class)
依赖库引入 Jackson(jackson-databind)或 Gson(gson
数据库字段类型推荐 JSON 类型(MySQL 5.7+/PostgreSQL jsonb),或 VARCHAR/TEXT
自定义处理逻辑继承 BaseTypeHandler 并实现序列化/反序列化方法

通过合理使用 JSON 类型处理器,可以极大简化复杂对象的数据库存储与查询,提升开发效率。

© 版权声明
THE END
喜欢就点个赞,支持一下吧!
点赞47 分享
评论 抢沙发
头像
欢迎您留下评论!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容