MyBatisPlus中JSON处理器的实现
作者:ruleslol
一、JSON 类型 在 Mysql中的使用
MySQL 5.7.8 版本开始就原生支持 JSON 类型了。
1-1、基本用法
建表时直接用 JSON 作为字段类型:
CREATE TABLE orders (
id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT,
extra JSON -- JSON 类型字段
);
插入数据:
INSERT INTO orders (user_id, extra) VALUES (1, '{"color": "red", "size": "XL"}');
1-2、常用的 JSON 函数
查询 JSON 中的某个字段:
-- -> 返回 JSON 格式,->> 返回纯文本 SELECT extra->'$.color' FROM orders; -- 返回 "red"(带引号) SELECT extra->>'$.color' FROM orders; -- 返回 red(不带引号)
修改 JSON 中的某个字段:
UPDATE orders SET extra = JSON_SET(extra, '$.color', 'blue') WHERE id = 1;
按 JSON 字段的值来查询:
SELECT * FROM orders WHERE extra->>'$.color' = 'red';
使用JSON_CONTAINS查询包含特定的值
select * from order where JSON_CONTAINS(extra, '"red"', '$.color');
1-3、和直接存 VARCHAR 字符串的区别
虽然你插入时写的是 JSON 字符串,但 MySQL 内部会把它解析并转换成二进制格式存储。
| 对比项 | JSON 类型 | VARCHAR 存 JSON 字符串 |
|---|---|---|
| 存储格式 | 二进制(优化过的) | 普通字符串 |
| 格式校验 | ✅ 插入时自动校验格式合法性 | ❌ 不校验,存什么都行 |
| 查询字段 | ✅ 支持 -> ->> 直接查内部字段 | ❌ 只能整体查,或用字符串函数 |
| 索引 | ✅ 支持对 JSON 内部字段建虚拟列索引 | ❌ 不支持 |
| 性能 | 读取内部字段更快 | 每次都要解析整个字符串 |
所以本质上存的是二进制,只是展示给你看的时候会格式化成 JSON 字符串的样子。
1-4、MySQL 内置的 JSON 操作函数:JSON_SET
JSON_SET 是 MySQL 内置的 JSON 操作函数,作用是修改 JSON 中某个字段的值,如果字段不存在就新增,存在就覆盖。
1、语法
JSON_SET(json字段, 路径, 新值, 路径, 新值, ...)
支持一次修改多个字段。
2、举个例子
假设 extra 字段当前值是:
{"color": "red", "size": "XL"}
修改已有字段:
UPDATE orders SET extra = JSON_SET(extra, '$.color', 'blue');
-- 结果:{"color": "blue", "size": "XL"}
新增不存在的字段:
UPDATE orders SET extra = JSON_SET(extra, '$.price', 99);
-- 结果:{"color": "red", "size": "XL", "price": 99}
同时修改多个:
UPDATE orders SET extra = JSON_SET(extra, '$.color', 'blue', '$.size', 'M');
-- 结果:{"color": "blue", "size": "M"}
3、相似函数对比
| 函数 | 作用 |
|---|---|
| JSON_SET | 有则覆盖,无则新增 |
| JSON_INSERT | 只新增,已存在的字段不覆盖 |
| JSON_REPLACE | 只覆盖,不存在的字段不新增 |
| JSON_REMOVE | 删除某个字段 |
大多数情况用 JSON_SET 就够了,因为它最灵活。
二、在 MyBatis-Plus 中使用
Java 实体类中对应字段用 String 或自定义对象接收,需要加json类型处理器。



【注意】:
没有application.yml全局配置!!!
2-1、完整示例
1、定义json类型字段对应的java类
@Data
@NoArgsConstructor
@AllArgsConstructor(staticName = "of")
public class JsonInfo {
private String color;
private String size;
}2、在对应的table entity类上添加两个注解:


3、postman测试
(1)查询

(2)插入

三、@TableName(autoResultMap = true) 详解
这是 MyBatis-Plus 框架中的注解属性,主要用于处理特殊类型字段的映射问题。
它的核心作用是:让 MyBatis-Plus 自动构建一个 ResultMap 并注入到 MyBatis 中,主要用于解决自定义类型处理器(TypeHandler)在查询时不生效的问题。
【备注】:
ResultMap 是 MyBatis 中用于定义数据库查询结果与 Java 对象之间映射关系的核心配置。
数据库查询结果 (ResultSet)
↓
ResultMap (映射规则)
↓
Java 对象 (POJO/Entity)简单说:ResultMap 告诉 MyBatis "如何把数据库的列映射到 Java 对象的属性"
ResultMap vs resultType
| 对比项 | resultType | resultMap |
|---|---|---|
| 配置方式 | 自动映射 | 手动配置映射规则 |
| 适用场景 | 字段名=属性名 | 字段名≠属性名/关联查询/类型转换 |
| 灵活性 | 低 | 高 |
| 代码量 | 少 | 多 |
| TypeHandler | 不支持 | ✅ 支持· |
3-1、核心含义
| 属性 | 默认值 | 作用 |
|---|---|---|
| autoResultMap | false | 是否自动构建 resultMap 并使用 resultMap 映射 |
当设置为 true 时,MyBatis-Plus 会自动生成 ResultMap,支持自定义类型处理器(TypeHandler)生效。
为什么需要它?
MyBatis 中,typeHandler(类型处理器)只有两种生效方式:
- 定义在 XML 的 <resultMap> 里 —— 只作用于查询结果封装
- 定义在 SQL 的 #{property, typeHandler=xxx} 中 —— 只作用于插入/更新设值
而 MyBatis-Plus 的通用 CRUD 方法(如 selectById、selectList)默认不走你手写的 ResultMap。
如果你在字段上用了 @TableField(typeHandler = XxxTypeHandler.class),但不开启 autoResultMap,查询时这个 TypeHandler 就不会被调用,导致字段值为 null。
开启 autoResultMap = true 后,MyBatis-Plus 会在启动时扫描实体类字段,自动生成包含 TypeHandler 配置的 ResultMap,这样内置查询方法就能正确映射复杂类型了。
3-2、典型使用场景
场景一:MySQL JSON 类型字段(最常见)
当数据库字段是 JSON 类型,实体类属性是 Java 对象/集合 时:
// 实体类
@TableName(value = "users", autoResultMap = true)
public class User {
@TableId
private Long id;
// JSON 字段,需要类型转换
@TableField(typeHandler = JacksonTypeHandler.class)
private UserInfo info;
@TableField(typeHandler = JacksonTypeHandler.class)
private List<String> tags;
}
# application.yml 配置 mybatis-plus: type-handlers-package: com.example.demo.handler type-aliases-package: com.example.demo.entity
场景二:比如你有个 MySQLJSON字段,想映射到 Java 的List或Map:
@Data
@TableName(value = "tb_user", autoResultMap = true) // 必须开启!
public class User {
private Long id;
private String name;
// JSON 字段 → Java List
@TableField(typeHandler = JacksonTypeHandler.class)
private List<Role> roles;
// JSON 字段 → Java Map
@TableField(typeHandler = JacksonTypeHandler.class)
private Map<String, Object> extra;
}不设置 autoResultMap = true → 查出来的 roles 和 extra 都是 null
设置了 autoResultMap = true → TypeHandler 生效,JSON 正确解析为 Java 对象
场景三:自定义 TypeHandler
// 自定义类型处理器
public class EncryptTypeHandler extends BaseTypeHandler<String> {
@Override
public void setParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) {
ps.setString(i, encrypt(parameter));
}
@Override
public String getNullableResult(ResultSet rs, String columnName) {
return decrypt(rs.getString(columnName));
}
// ... 其他方法
}
// 实体类
@TableName(value = "users", autoResultMap = true)
public class User {
@TableField(typeHandler = EncryptTypeHandler.class)
private String phone; // 数据库中加密存储
}
3-3、注意事项
| 问题 | 说明 |
|---|---|
| 必须配合 TypeHandler | 只设置 autoResultMap=true 不够,字段上还需加 @TableField(typeHandler=...) |
| XML 映射文件 | 如果使用 XML,需要在 resultMap 中指定 typeHandler |
| 性能影响 | 开启后会生成额外 ResultMap,轻微影响性能 |
| MP 版本 | 3.3.1+ 版本支持较好 |
3-4、完整示例
// 实体类
@TableName(value = "articles", autoResultMap = true)
@Data
public class Article {
@TableId
private Long id;
private String title;
// JSON 字段存储为对象
@TableField(typeHandler = JacksonTypeHandler.class)
private ArticleContent content;
// JSON 字段存储为列表
@TableField(typeHandler = JacksonTypeHandler.class)
private List<String> tags;
}
// JSON 对象
@Data
public class ArticleContent {
private String text;
private String coverImage;
private Integer wordCount;
}
// Mapper 接口
@Mapper
public interface ArticleMapper extends BaseMapper<Article> {
// 自定义查询也需要 ResultMap 支持
@Select("SELECT * FROM articles WHERE id = #{id}")
Article selectDetail(Long id);
}
3-5、什么时候需要设置?
| 情况 | 是否需要 |
|---|---|
| 普通字段映射 | ❌ 不需要 |
| 数据库 JSON → Java 对象 | ✅ 需要 |
| 数据库 JSON → Java 集合 | ✅ 需要 |
| 使用自定义 TypeHandler | ✅ 需要 |
| 字段加密/脱敏处理 | ✅ 需要 |
一句话:只要用了 @TableField(typeHandler = ...),实体类就必须加 @TableName(autoResultMap = true),否则查询时 TypeHandler 不生效。
3-6、自动生成的 ResultMap 名称
MyBatis-Plus 自动注入的 ResultMap 名称格式为:
| 格式 | 示例 |
|---|---|
| 短名称 | mybatis-plus_Xxx |
| 长名称(全限定) | com.example.mapper.UserMapper.mybatis-plus_Xxx |
如果你在自己的 Mapper 里写自定义 SQL,想复用这个自动 ResultMap:
@Mapper
public interface UserMapper extends BaseMapper<User> {
@ResultMap("mybatis-plus_User") // 引用自动生成的 ResultMap
@Select("SELECT * FROM tb_user WHERE age > #{age}")
List<User> selectByAge(@Param("age") Integer age);
}总结
autoResultMap = true
↓
让 MyBatis-Plus 自动生成 ResultMap
↓
使 @TableField(typeHandler = ...) 生效
↓
实现 数据库特殊类型 ↔ Java 对象 的转换简单说:处理 JSON 字段或自定义类型转换时,必须开启这个选项!
到此这篇关于MyBatisPlus中JSON处理器的实现的文章就介绍到这了,更多相关MyBatisPlus JSON处理器内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
