MyBatis-Plus12:JSON处理器

一、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 字段或自定义类型转换时,必须开启这个选项!

相关推荐
ruleslol6 小时前
MyBatis-Plus13:自定义 TypeHandler
mybatis-plus
ruleslol2 天前
MyBatis-Plus07:rewriteBatchedStatements 参数详解与批处理
mybatis-plus
ruleslol2 天前
MyBatis-Plus08:代码生成
mybatis-plus
ruleslol2 天前
MyBatis-Plus09:静态工具Db
mybatis-plus
树码小子2 天前
Mybatis(17)Mybatis-Plus条件构造器(2)& 自定义 SQL
数据库·sql·mybatis-plus
ruleslol2 天前
MyBatis-Plus10:逻辑删除
mybatis-plus
树码小子3 天前
Mybatis(16)Mybatis-Plus条件构造器(1)
数据库·mybatis-plus
树码小子4 天前
Mybatis(14)Mybatis-Plus入门 & 简单使用
java·mybatis-plus
ruleslol5 天前
MyBatis-Plus06:IService接口Lambda基本用法
mybatis-plus