java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > MyBatisPlus JSON处理器

MyBatisPlus中JSON处理器的实现

作者:ruleslol

本文主要介绍了MyBatisPlus中JSON处理器的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

一、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

对比项resultTyperesultMap
配置方式自动映射手动配置映射规则
适用场景字段名=属性名字段名≠属性名/关联查询/类型转换
灵活性
代码量
TypeHandler不支持✅ 支持·

3-1、核心含义

属性默认值作用
autoResultMapfalse是否自动构建 resultMap 并使用 resultMap 映射

当设置为 true 时,MyBatis-Plus 会自动生成 ResultMap,支持自定义类型处理器(TypeHandler)生效。

为什么需要它?

MyBatis 中,typeHandler(类型处理器)只有两种生效方式:

而 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处理器内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文