目录
[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