一、JSON 类型 在 Mysql中的使用
MySQL 5.7.8 版本开始就原生支持 JSON 类型了。
1-1、基本用法
建表时直接用 JSON 作为字段类型:
sql
CREATE TABLE orders (
id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT,
extra JSON -- JSON 类型字段
);
插入数据:
sql
INSERT INTO orders (user_id, extra) VALUES (1, '{"color": "red", "size": "XL"}');
1-2、常用的 JSON 函数
查询 JSON 中的某个字段:
sql
-- -> 返回 JSON 格式,->> 返回纯文本
SELECT extra->'$.color' FROM orders; -- 返回 "red"(带引号)
SELECT extra->>'$.color' FROM orders; -- 返回 red(不带引号)
修改 JSON 中的某个字段:
sql
UPDATE orders SET extra = JSON_SET(extra, '$.color', 'blue') WHERE id = 1;
按 JSON 字段的值来查询:
sql
SELECT * FROM orders WHERE extra->>'$.color' = 'red';
1-3、和直接存 VARCHAR 字符串的区别
虽然你插入时写的是 JSON 字符串,但 MySQL 内部会把它解析并转换成二进制格式存储。
| 对比项 | JSON 类型 | VARCHAR 存 JSON 字符串 |
|---|---|---|
| 存储格式 | 二进制(优化过的) | 普通字符串 |
| 格式校验 | ✅ 插入时自动校验格式合法性 | ❌ 不校验,存什么都行 |
| 查询字段 | ✅ 支持 -> ->> 直接查内部字段 |
❌ 只能整体查,或用字符串函数 |
| 索引 | ✅ 支持对 JSON 内部字段建虚拟列索引 | ❌ 不支持 |
| 性能 | 读取内部字段更快 | 每次都要解析整个字符串 |
所以本质上存的是二进制,只是展示给你看的时候会格式化成 JSON 字符串的样子。
1-4、MySQL 内置的 JSON 操作函数:JSON_SET
JSON_SET 是 MySQL 内置的 JSON 操作函数,作用是修改 JSON 中某个字段的值,如果字段不存在就新增,存在就覆盖。
1、语法
sql
JSON_SET(json字段, 路径, 新值, 路径, 新值, ...)
支持一次修改多个字段。
2、举个例子
假设 extra 字段当前值是:
sql
{"color": "red", "size": "XL"}
修改已有字段:
sql
UPDATE orders SET extra = JSON_SET(extra, '$.color', 'blue');
-- 结果:{"color": "blue", "size": "XL"}
新增不存在的字段:
sql
UPDATE orders SET extra = JSON_SET(extra, '$.price', 99);
-- 结果:{"color": "red", "size": "XL", "price": 99}
同时修改多个:
sql
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类
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 框架中的注解属性,主要用于处理特殊类型字段的映射问题。
【备注】:
ResultMap 是 MyBatis 中用于定义数据库查询结果与 Java 对象之间映射关系的核心配置。
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)生效。
3-2、典型使用场景
场景一:MySQL JSON 类型字段(最常见)
当数据库字段是 JSON 类型 ,实体类属性是 Java 对象/集合 时:
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;
}
bash
# application.yml 配置
mybatis-plus:
type-handlers-package: com.example.demo.handler
type-aliases-package: com.example.demo.entity
场景二:自定义 TypeHandler
java
// 自定义类型处理器
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));
}
// ... 其他方法
}
java
// 实体类
@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、完整示例
java
// 实体类
@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;
}
java
// JSON 对象
@Data
public class ArticleContent {
private String text;
private String coverImage;
private Integer wordCount;
}
java
// 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 | ✅ 需要 |
| 字段加密/脱敏处理 | ✅ 需要 |
总结
java
autoResultMap = true
↓
让 MyBatis-Plus 自动生成 ResultMap
↓
使 @TableField(typeHandler = ...) 生效
↓
实现 数据库特殊类型 ↔ Java 对象 的转换
简单说:处理 JSON 字段或自定义类型转换时,必须开启这个选项!