MybatisPlus作为Mybatis的增强工具,简化了数据库操作的很多流程,但在处理MySQL的json类型字段时,需要额外配置才能实现正确的映射和读写,否则会出现字段无法解析、数据插入失败等问题。

MySQL json类型字段的表定义
首先需要在MySQL中创建包含json类型字段的表,示例如下:
-- 创建用户扩展信息表,其中ext_info为json类型字段
CREATE TABLE user_extend (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
user_id BIGINT NOT NULL COMMENT '用户ID',
ext_info JSON COMMENT '用户扩展信息,存储爱好、地址等结构化数据',
create_time DATETIME DEFAULT CURRENT_TIMESTAMP
);
定义json字段对应的实体类
json类型字段在Java实体类中可以用两种方式定义,一种是直接用String类型接收,另一种是定义为自定义的对象类型,这里我们以自定义对象为例,首先定义扩展信息的实体类:
import lombok.Data;
import java.util.List;
@Data
public class UserExtInfo {
// 用户爱好列表
private List<String> hobbies;
// 用户居住地址
private String address;
// 用户年龄
private Integer age;
}
接着定义对应数据库表的MybatisPlus实体类:
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.IdType;
import lombok.Data;
@Data
@TableName("user_extend")
public class UserExtend {
@TableId(type = IdType.AUTO)
private Long id;
private Long userId;
// 这里的typeHandler指定后续自定义的json类型处理器
private UserExtInfo extInfo;
private LocalDateTime createTime;
}
自定义TypeHandler处理json映射
MybatisPlus默认没有提供直接的json类型处理器,需要自定义TypeHandler来实现Java对象和MySQL json字段的互相转换,这里我们基于Jackson实现序列化反序列化:
import com.baomidou.mybatisplus.extension.handlers.AbstractJsonTypeHandler;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
public class UserExtInfoTypeHandler extends AbstractJsonTypeHandler<UserExtInfo> {
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
public UserExtInfoTypeHandler(Class<UserExtInfo> type) {
super(type);
}
@Override
protected UserExtInfo parse(String json) {
try {
return OBJECT_MAPPER.readValue(json, UserExtInfo.class);
} catch (JsonProcessingException e) {
throw new RuntimeException("json解析失败", e);
}
}
@Override
protected String toJson(UserExtInfo obj) {
try {
return OBJECT_MAPPER.writeValueAsString(obj);
} catch (JsonProcessingException e) {
throw new RuntimeException("对象转json失败", e);
}
}
}
注册TypeHandler并配置映射
有两种方式配置类型处理器,一种是在实体类字段上直接指定,另一种是在MybatisPlus配置类中全局注册。
实体类字段指定方式
在实体类的extInfo字段上添加@TableField注解指定类型处理器:
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;
import lombok.Data;
@Data
@TableName("user_extend")
public class UserExtend {
@TableId(type = IdType.AUTO)
private Long id;
private Long userId;
@TableField(typeHandler = UserExtInfoTypeHandler.class)
private UserExtInfo extInfo;
private LocalDateTime createTime;
}
全局配置方式
在MybatisPlus的配置类中注册类型处理器,这样所有匹配的字段都会自动使用该处理器:
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@MapperScan("com.example.mapper")
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
然后在application.yml中配置类型处理器的扫描路径:
mybatis-plus:
type-handlers-package: com.example.handler
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
增删改查操作示例
配置完成后就可以正常使用MybatisPlus的CRUD接口操作json字段了。
新增数据
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.example.entity.UserExtend;
import com.example.entity.UserExtInfo;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.Arrays;
@SpringBootTest
class UserExtendTest {
@Autowired
private UserExtendMapper userExtendMapper;
@Test
void testInsert() {
UserExtend userExtend = new UserExtend();
userExtend.setUserId(1001L);
UserExtInfo extInfo = new UserExtInfo();
extInfo.setHobbies(Arrays.asList("篮球", "阅读"));
extInfo.setAddress("北京市海淀区");
extInfo.setAge(25);
userExtend.setExtInfo(extInfo);
userExtendMapper.insert(userExtend);
System.out.println("新增成功,主键ID:" + userExtend.getId());
}
}
查询数据
@Test
void testSelect() {
LambdaQueryWrapper<UserExtend> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(UserExtend::getUserId, 1001L);
UserExtend userExtend = userExtendMapper.selectOne(queryWrapper);
System.out.println("用户扩展信息:" + userExtend.getExtInfo());
System.out.println("用户爱好:" + userExtend.getExtInfo().getHobbies());
}
更新json字段数据
@Test
void testUpdate() {
LambdaQueryWrapper<UserExtend> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(UserExtend::getUserId, 1001L);
UserExtend userExtend = userExtendMapper.selectOne(queryWrapper);
UserExtInfo extInfo = userExtend.getExtInfo();
extInfo.setAge(26);
extInfo.getHobbies().add("旅游");
userExtend.setExtInfo(extInfo);
userExtendMapper.updateById(userExtend);
System.out.println("更新成功");
}
注意事项
- 如果json字段存储的是简单结构,也可以直接用String类型接收,不需要自定义TypeHandler,查询后手动解析即可
- 自定义TypeHandler时,如果json结构和实体类不匹配,会抛出解析异常,需要确保两边的字段对应
- 全局配置TypeHandler时,要确保handler的包路径正确,否则不会生效
- 如果使用MybatisPlus的XML映射文件写自定义SQL,需要在字段映射时显式指定typeHandler
MybatisPlusMySQLjson类型TypeHandler修改时间:2026-07-24 12:15:37