MyBatis-Plus LambdaQuery 高级用法:JSON 路径查询与条件拼接的全场景解析

目录

[1. 查询 JSON 字段中的特定值](#1. 查询 JSON 字段中的特定值)

[2. 动态查询 JSON 字段中的值](#2. 动态查询 JSON 字段中的值)

[3. 查询 JSON 数组中的值](#3. 查询 JSON 数组中的值)

[4. 查询 JSON 字段中的嵌套对象](#4. 查询 JSON 字段中的嵌套对象)

[5. 结合其他条件查询 JSON 字段](#5. 结合其他条件查询 JSON 字段)

[6. 使用类型处理器简化 JSON 查询](#6. 使用类型处理器简化 JSON 查询)

[6.1 创建自定义 JSON 类型处理器](#6.1 创建自定义 JSON 类型处理器)

[6.2 在实体类中指定自定义类型处理器](#6.2 在实体类中指定自定义类型处理器)

示例代码

[6.3 配置类型处理器包(可选)](#6.3 配置类型处理器包(可选))

[6.4 使用自定义类型处理器](#6.4 使用自定义类型处理器)

[7. 使用内置的 JacksonTypeHandler 或 FastjsonTypeHandler](#7. 使用内置的 JacksonTypeHandler 或 FastjsonTypeHandler)

1. 查询 JSON 字段中的特定值

假设有一个表 user,其中包含一个 JSON 字段 info,存储了用户的一些额外信息。如果要查询 info 字段中 age 大于 20 的用户,可以使用以下代码:

java 复制代码
LambdaQueryWrapper<User> queryWrapper = Wrappers.lambdaQuery();
queryWrapper.apply("JSON_EXTRACT(info, '$.age') > {0}", 20);
List<User> users = userMapper.selectList(queryWrapper);

这里通过 apply 方法嵌入了 MySQL 的 JSON_EXTRACT 函数。

2. 动态查询 JSON 字段中的值

如果需要根据动态条件查询 JSON 字段中的值,例如根据用户输入的条件查询 info 字段中 gender 为 "male" 的用户,可以这样实现:

java 复制代码
LambdaQueryWrapper<User> queryWrapper = Wrappers.lambdaQuery();
if ("male".equals(gender)) {
    queryWrapper.apply("JSON_EXTRACT(info, '$.gender') = {0}", "\"male\"");
}
List<User> users = userMapper.selectList(queryWrapper);

这种方式可以根据条件动态添加查询语句。

3. 查询 JSON 数组中的值

假设 info 字段是一个 JSON 数组,存储了用户的多个兴趣爱好,要查询兴趣爱好中包含 "reading" 的用户:

java 复制代码
LambdaQueryWrapper<User> queryWrapper = Wrappers.lambdaQuery();
queryWrapper.apply("JSON_CONTAINS(info, {0})", "\"reading\"");
List<User> users = userMapper.selectList(queryWrapper);

这里使用了 MySQL 的 JSON_CONTAINS 函数。

4. 查询 JSON 字段中的嵌套对象

如果 JSON 字段中包含嵌套对象,例如 info 字段中有一个 address 对象,要查询 address 中的 city 为 "Beijing" 的用户:

java 复制代码
LambdaQueryWrapper<User> queryWrapper = Wrappers.lambdaQuery();
queryWrapper.apply("JSON_EXTRACT(info, '$.address.city') = {0}", "\"Beijing\"");
List<User> users = userMapper.selectList(queryWrapper);

通过指定 JSON 路径,可以查询嵌套对象中的值。

5. 结合其他条件查询 JSON 字段

可以将 JSON 字段的查询与其他普通字段的查询条件结合使用。例如,查询状态为 "active" 且 info 字段中 age 大于 20 的用户:

java 复制代码
LambdaQueryWrapper<User> queryWrapper = Wrappers.lambdaQuery();
queryWrapper.eq(User::getStatus, "active")
             .apply("JSON_EXTRACT(info, '$.age') > {0}", 20);
List<User> users = userMapper.selectList(queryWrapper);

这种方式可以灵活地组合多种查询条件。

6. 使用类型处理器简化 JSON 查询

从 MyBatis-Plus 3.5.3.2 版本开始,可以在 Wrapper 查询中直接使用类型处理器。例如,假设有一个自定义的 JSON 类型处理器 UserInfoTypeHandler,可以这样使用:

java 复制代码
LambdaQueryWrapper<User> queryWrapper = Wrappers.lambdaQuery();
queryWrapper.apply("info = {0, typeHandler=" + UserInfoTypeHandler.class.getCanonicalName() + "}", "{\"age\":20,\"gender\":\"male\"}");
List<User> users = userMapper.selectList(queryWrapper);

通过类型处理器,可以更方便地处理 JSON 数据

6.1 创建自定义 JSON 类型处理器

自定义的 JSON 类型处理器需要继承 BaseTypeHandler 或 AbstractJsonTypeHandler 等内置类型处理器,并实现相关方法。

示例代码

以下是一个基于 Jackson 的自定义 JSON 类型处理器示例:

java 复制代码
import com.baomidou.mybatisplus.extension.handlers.AbstractJsonTypeHandler;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

@MappedTypes({Object.class}) // 指定支持的 Java 类型
@MappedJdbcTypes(JdbcType.VARCHAR) // 指定对应的 JDBC 类型
public class CustomJsonTypeHandler<T> extends AbstractJsonTypeHandler<T> {
    private static final ObjectMapper objectMapper = new ObjectMapper();

    public CustomJsonTypeHandler(Class<T> type) {
        super(type);
    }

    @Override
    protected T parse(String json) {
        try {
            return objectMapper.readValue(json, getType());
        } catch (Exception e) {
            throw new RuntimeException("Failed to parse JSON", e);
        }
    }

    @Override
    protected String toJson(T obj) {
        try {
            return objectMapper.writeValueAsString(obj);
        } catch (Exception e) {
            throw new RuntimeException("Failed to serialize object to JSON", e);
        }
    }
}
6.2 在实体类中指定自定义类型处理器

在实体类中,通过 @TableField 注解指定自定义的类型处理器。

示例代码

假设有一个 User 实体类,其中 info 字段是一个 JSON 字段,存储用户的一些额外信息:

java 复制代码
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;

@Data
@TableName(value = "user", autoResultMap = true)
public class User {
    private Long id;
    private String name;

    @TableField(typeHandler = CustomJsonTypeHandler.class)
    private UserInfo info; // UserInfo 是一个自定义的 Java 类
}
6.3 配置类型处理器包(可选)

如果自定义的类型处理器不在默认扫描路径下,可以在 application.yml 中指定类型处理器的包路径:

XML 复制代码
mybatis-plus:
  type-handlers-package: com.yourpackage.handler
6.4 使用自定义类型处理器

在 MyBatis-Plus 的增删改查操作中,自定义的类型处理器会自动生效。例如:

java 复制代码
User user = new User();
user.setName("Alice");
user.setInfo(new UserInfo("Beijing", 25)); // 设置 JSON 字段
userMapper.insert(user);

// 查询时,info 字段会自动解析为 UserInfo 对象
User queriedUser = userMapper.selectById(user.getId());
System.out.println(queriedUser.getInfo().getCity()); // 输出 Beijing

通过以上步骤,你可以在 MyBatis-Plus 中使用自定义的 JSON 类型处理器来处理数据库中的 JSON 字段

7. 使用内置的 JacksonTypeHandler 或 FastjsonTypeHandler

MyBatis-Plus 提供了内置的 JSON 类型处理器,如 JacksonTypeHandler 和 FastjsonTypeHandler,可以直接将 JSON 字段映射为 JSONObject 或其他 JSON 类型。

示例代码

假设有一个表 user,其中 info 是一个 JSON 字段,存储用户的一些额外信息。在实体类中,可以这样配置:

java 复制代码
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;

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

    @TableField(typeHandler = JacksonTypeHandler.class)
    private JSONObject info; // 使用 JSONObject
}

在 MyBatis-Plus 的增删改查操作中,info 字段会自动被解析为 JSONObject

相关推荐
stillstream_ink2 小时前
一个缺失的状态校验,让 Mall4j 的订单系统开了 4 个后门
mysql·测试
PC2005-cloud3 小时前
MySQL学习笔记:主从复制集群搭建以及原理详解
笔记·学习·mysql
夜雪一千3 小时前
MySQL中修改JSON类型的数据实战
数据库·mysql·json
承渊政道3 小时前
【Python编程—从入门到实践】(让程序记得、恢复并解释失败:Python 文件、异常与JSON系统教程)
开发语言·python·pycharm·json·异常处理
for_ever_love__4 小时前
MySQL 优化器与 OPTIMIZER_TRACE:把‘为什么选这条计划‘问到水落石出
数据库·mysql·优化器·trace·optimizer·执行计划分析·cic
靠沿4 小时前
MySQL数据库基础——事务
java·数据库·mysql
夜雪一千4 小时前
MySQL 中查询和操作JSON类型的数据
数据库·mysql·json
AIgorithmGEEK13 小时前
MySQL 索引全解(下):建、查、删实战与知识速查表
数据库·mysql·b+树·索引
Lost_the_wind13 小时前
MySQL学习笔记四
mysql
geovindu18 小时前
sql:Search-Optimized SQL Queries using mysql 9.0
android·数据库·sql·mysql·数据库开发·数据库架构