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 类型处理器需要继承 BaseTypeHandlerAbstractJsonTypeHandler 等内置类型处理器,并实现相关方法。

示例代码

以下是一个基于 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. 使用内置的 JacksonTypeHandlerFastjsonTypeHandler

MyBatis-Plus 提供了内置的 JSON 类型处理器,如 JacksonTypeHandlerFastjsonTypeHandler,可以直接将 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

相关推荐
snow@li2 小时前
vue3+ts+vite:详细、完整的 tsconfig.json 示例 / 常见配置项及其用途
json·tsconfig.json
南郁3 小时前
007-nlohmann/json 项目应用-C++开源库108杰
c++·开源·json·nlohmann·现代c++·d2school·108杰
紫乾20145 小时前
idea json生成实体类
java·json·intellij-idea
yuren_xia6 小时前
Spring Boot + MyBatis 集成支付宝支付流程
spring boot·tomcat·mybatis
天天摸鱼的java工程师6 小时前
高考放榜夜,系统别崩!聊聊查分系统怎么设计,三张表足以?
java·后端·mysql
exe4527 小时前
jdbc查询mysql数据库时,出现id顺序错误的情况
数据库·mysql
Johny_Zhao8 小时前
阿里云数据库Inventory Hint技术分析
linux·mysql·信息安全·云计算·系统运维
loserkk8 小时前
MySQL InnoDB 5.7 索引失效场景解析:原理与案例
mysql
L.S.V.10 小时前
MYSQL(三)--服务器启动参数与配置
服务器·数据库·mysql
有时间要学习10 小时前
MySQL——视图 && 用户管理 && 语言访问
数据库·mysql