Mybatis存取json字段转为Java对象方案
背景:
项目中有一些数据只需要查询,不需要检索,这些数据可以通过存储jsonStr,存储在关系型数据库中。
假设,我们需要记录动物园小动物的一些信息,我们就可以新建一张animal表,
但是不同种类的小动物身上有不同的信息,比如大象需要记录象牙的长度,这个信息,在其他小动物上是没有的,不属于通用属性,这种信息以jsonStr的格式存到数据库中就比较合适。但是我们的代码中还是想用对象来接收数据,持久话层使用的是mybatis 的话,需要使用mybatis 自定义类型转换器。
自定义typeHandler并使用,共有两个步骤
- 自定义TypeHandler,继承BaseTypeHandler或者实现TypeHandler
- 在mapper中配置所需要自定义TypeHandler的地方,如resultMap中指定参数。
1. 自定义TypeHandler#
import cn.hutool.json.JSONUtil;
/**
继承BaseTypeHandler,实现一个json转object通用的类
注意:这里的json工具类使用的时hutool中的JSONUtil,用fastjson或其他json框架的注意替换
*/
public class AbstractObjectTypeHandler<T> extends BaseTypeHandler<T> {
@Override
public void setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException {
ps.setString(i, JSONUtil.toJsonStr(parameter));
}
@Override
public T getNullableResult(ResultSet rs, String columnName)
throws SQLException {
String data = rs.getString(columnName);
return StringUtils.isBlank(data) ? null : JSONUtil.toBean(data, (Class<T>) getRawType());
}
@Override
public T getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
String data = rs.getString(columnIndex);
return StringUtils.isBlank(data) ? null : JSONUtil.toBean(data, (Class<T>) getRawType());
}
@Override
public T getNullableResult(CallableStatement cs, int columnIndex)
throws SQLException {
String data = cs.getString(columnIndex);
return StringUtils.isBlank(data) ? null : JSONUtil.toBean(data, (Class<T>) getRawType());
}
}
@MappedJdbcTypes({JdbcType.VARCHAR})
@MappedTypes({Info.class})
public class UserInfoHandler extends AbstractObjectTypeHandler<Info>{
// 继承通用json转Object的AbstractObjectTypeHandler,指定所转class类型
}
public class User{
private String name;
private Integer age;
private Info info;
}
public class Info{
private String usedName;
private Integer height;
}
2. 在mapper中配置#
我们定义了MyDateTypeHandler,需要在mapper中配置:
- 查询时,查询时我们配置resultMap
- 插入、修改时,我们有三种配置方式
- javaType,jdbcType ,TypeHandler都指定
- 指定javaType,jdbcType
- 只指定typeHandler
<!--配置resultMap-->
<resultMap id="userResultMap" type="org.sang.bean.User">
<result typeHandler="com.zyy.handler.UserInfoHandler" column="info" javaType="com.zyy.domain.Info"
jdbcType="VARCHAR"
property="info"/>
</resultMap>
<!--查询-->
<select id="getUser" resultMap="userResultMap">
select * from user
</select>
<!--1. javaType,jdbcType ,TypeHandler都指定-->
<insert id="insertUser" parameterType="org.sang.bean.User">
INSERT INTO user(name,age,info) VALUES (#{name},#{age},#{info,javaType=com.zyy.domain.Info,jdbcType=VARCHAR,typeHandler=com.zyy.handler.UserInfoHandler})
</insert>
<!--2. 指定javaType,jdbcType-->
<insert id="insertUser2">
INSERT INTO user(name,age,info) VALUES (#{name},#{age},#{info,javaType=com.zyy.domain.Info,jdbcType=VARCHAR})
</insert>
<!--3. 只指定typeHandler-->
<insert id="insertUser3">
INSERT INTO user(name,age,info) VALUES (#{name},#{age},#{info,typeHandler=com.zyy.handler.UserInfoHandler})
</insert>
除了在mapper文件中配置,我们也可以通过配置文件将typeHandler注册进去,但是这种方式只能结果读取时数据的转换
mybatis:
# 配置扫描包
typeHandlersPackage: com.hc.etf.config.typeHandel
更多 Mybatis TypeHandler 相关知识可见:https://www.cnblogs.com/zhaoyuan72/p/14475120.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY