【保姆级】使用Mybatis的TypeHandler优雅的存取自定义类型

更新时间:2023-06-30 21:35:11 阅读: 评论:0

【保姆级】使⽤Mybatis的TypeHandler优雅的存取⾃定义类型
经典英文台词
在⽹上找了很多⽂章,要么太浅,要么太深,案例较少,所以⾃⼰总结了⼀篇保姆级的使⽤教程
⽂中主要举了三种⽐较常见的例⼦(⾃定义类、⾃定义枚举、⾃定义类的集合)
快速使⽤直接跳到结论即可
本⽂仅讲述使⽤mybatis-plus的注解⽅式实现(XML配置实现见最下⽅的参考资料)
⽂章⽬录
1 问题描述
创建的Java实体类中含有⾃定义的对象/枚举,想把这个⾃定义的对象/枚举,以某种格式存⼊到数据库,再从数据库取出后得到⾃定义的类型。有时⾃定义的类型也会放在集合中进⾏存取。
2 场景举例
2.1 需要将Ur对象存⼊到数据库
public class Ur{
private Integer id;
private String name;
private UrInfo urInfo;
}
public class UrInfo {
private String address;
private String phone;
}
2.2 以往的解决⽅案
public class Ur{
private Integer id;
private String name;
private String urInfo;
}
将Ur中urInfo的类型改为String,在保存到Ur之前就将UrInfo转成Json格式的字符串,然后保存到urInfo中,最后将Ur存⼊数据库
缺点:略显繁琐,每次存取之前都要进⾏JSON转换
衡山四绝当然你可能只需要把数据库保存的字符串类型的JSON数据返还给前端即可,但是如果你在后端需要利⽤这个JSON中的⼀些数据进⾏⼀些业务逻辑判断和操作的话,还是需要将这个字符串类型的JSON数据转换为⾃定义的对象,所以不如⼀劳永逸,在实体类中就使⽤⾃定义的类型。
2.3 直接将Ur对象存⼊到数据库
插⼊失败,因为mybatis⽆法识别我们⾃定义的UrInfo
2.4 解决⽅法
使⽤TypeHandle
3 了解TypeHandler
前提:我们通过mybatis对数据库的存取都要通过TypeHandler进⾏类型转换
举个例⼦:Java中定义了UrInfo类型,但是数据库不认识,我们现在就需要将UrInfo转换为数据库认识的类型
3.1 为什么Java⾃带的类型在存取的时候不会出错,我们⾃定义的类型就会出错
mybatis已经将这些类型的TypeHandler提前写好了
3.2 TypeHandler解决了什么问题?
1.可以指定我们在Java实体类所包含的⾃定义类型存⼊数据库后的类型是什么
2.从数据库中取出该数据后⾃动转换为我们⾃定义的Java类型
3.3 使⽤TypeHandler之前需要明确的事
1.想让当前实体类中⾃定义的对象存⼊到数据库后是什么格式
2.想让这个字段取出后是什么格式(通常来说,存⼊前和取出后都是想要我们⾃定义的类型)
3.4 BaTypeHandler
这个类型是抽象类型,实现了 TypeHandler 的⽅法进⾏通⽤流程的封装,做了异常处理,并定义了⼏个类似的抽象⽅法。
继承 BaTypeHandler 类型可以极⼤地降低开发难度。
4 使⽤TypeHandler
4.1 继承BaTypeHandler
继承BaTypeHandler后需要实现四个⽅法
4.1.1 tNonNullParameter(插⼊时设置参数类型)
preparedStatement:SQL预编译对象
i:需要赋值的索引位置(相当于在JDBC中对占位符的位置进⾏赋值)
urInfo:索引位置i需要赋的值(原本要给这个位置赋的值,在tNonNullParameter⽅法中主要解决的问题就是将这个⾃定义类型变成数据库认识的类型) jdbcType:jdbc的类型
public void tNonNullParameter(PreparedStatement preparedStatement, int i, UrInfo urInfo, JdbcType jdbcType)
注意:第三个参数为BaTypeHandler的泛型(这个反省就是要进⾏映射的Java类),实现⽅法的时候⾃动⽣成。
4.1.2 getNullableResult(获取时转换回的⾃定义类型)
根据列名获取
resultSet:结果集
columnName:列名
public UrInfo getNullableResult(ResultSet resultSet, String columnName)
根据索引位置获取
resultSet:结果集
columnIndex:列索引
public UrInfo getNullableResult(ResultSet resultSet, int columnIndex)
根据存储过程获取
callableStatement:结果集
columnIndex:列索引
public UrInfo getNullableResult(CallableStatement callableStatement, int columnIndex)
取得结果,供存储过程使⽤,针对存储过程⽽设,通过列下标的⽅式来获取存储过程输出结果中的数据
getNullableResult详细的调⽤过程在DefaultResultSetHandler类,搜索:Result
4.1.3 完整⽰例
成人大全
这⾥是将UrInfo转换为Json格式的字符串,然后插⼊数据库(这⾥转换Json使⽤了⾃⼰写的⼀个⼯具类JsonUtils封装的Gson,后⾯附带源码)
从数据库中取出Json格式的UrInfo,然后转换为UrInfo对象
4.2 相关注解
4.2.1 @TableName
来⾃mybatisplus
使⽤位置:实体类上
其中包含⼀个属性:autoResultMap
可取值:true(⾃动构建)、fal(不⾃动构建)
作⽤:表⽰是否⾃动构建resultMap 并使⽤
注意:在使⽤TypeHandler的时候需要指定autoResultMap为true,否则⽆效
4.2.2 @TableField
来⾃mybatisplus
马云创业经历使⽤位置:实体类中的属性上
其中包含⼀个属性:typeHandler
可取值:继承了TypeHandler的⾃定义TypeHandler
作⽤:指定该字段使⽤哪个TypeHandler进⾏类型转换
注意:在使⽤TypeHandler的时候需要指定typeHandler,否则⽆效
名实相副4.1.3 @MappedTypes
来⾃mybatis
使⽤位置:⾃定义的TypeHandler类上
可取值:Java类
作⽤:需要进⾏映射(转换)的Java类
4.1.4 @MappedJdbcTypes
来⾃mybatis
使⽤位置:⾃定义的TypeHandler类上
作⽤:需要转换为数据库中的什么类型(使⽤mybatis中的JdbcType枚举类进⾏声明) 5 使⽤⽰例
5.1 转换对象
Ur
/**
* @Author ChenJiahao(五条)
* @Date 2021/8/21 19:34
*/
小雨沙沙教案
@Data
@TableName(value = "ur",autoResultMap = true)
public class Ur {
@TableId(type = IdType.AUTO)
private Integer id;
private String name;
@TableField(value = "ur_info",typeHandler = UrInfoTypeHandler.class)
private UrInfo urInfo;
}
UrInfo
/**
* @Author ChenJiahao(五条)
* @Date 2021/8/21 19:36
*/
@Data
public class UrInfo {
private String address;
private String phone;
}
5.1.1 没有⾃定义TypeHandler以及没有在实体类中加注解的时候插⼊Ur失败
因为UrInfo不是Java⾃带的类型,所以我们在插⼊这个类型mybatis⽆法识别
获取Ur失败
这⾥可以看到,数据库确实查询到了该数据,没有设置映射规则,所以为null。
5.1.2 定义UrInfoTypeHandler
鳝鱼/**
* @Author ChenJiahao(五条)
* @Date 2021/8/21 21:05
*/
@MappedTypes(UrInfo.class)
@MappedJdbcTypes(JdbcType.VARCHAR)
public class UrInfoTypeHandler extends BaTypeHandler<UrInfo> {
@Override
public void tNonNullParameter(PreparedStatement preparedStatement, int i, UrInfo urInfo, JdbcType jdbcType) throws SQLException {        preparedStatement.tString(i, Json(urInfo));
}
@Override
public UrInfo getNullableResult(ResultSet resultSet, String columnName) throws SQLException {
return JsonUtils.String(columnName),UrInfo.class);
}
@Override
public UrInfo getNullableResult(ResultSet resultSet, int columnIndex) throws SQLException {
return JsonUtils.String(columnIndex),UrInfo.class);
工作承诺
}
@Override
public UrInfo getNullableResult(CallableStatement callableStatement, int columnIndex) throws SQLException {
return JsonUtils.String(columnIndex),UrInfo.class);
}
}
5.1.3 分析UrInfoTypeHandler
在tNonNullParameter⽅法中
将当前UrInfo对象通过Json转换为Json格式的字符串,然后通过JDBC的⽅式将字符串填充到占位符
在getNullableResult⽅法中
因为UrInfo在数据库中保存的是Json格式的字符串,所以先将该字符串通过JsonUtils.fromJson转换为UrInfo再进⾏返回5.1.4 ⾃定义TypeHandler,在实体类中加⼊注解
插⼊Ur成功
获取Ur成功
5.2 转换枚举
Teacher

本文发布于:2023-06-30 21:35:11,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/82/1070923.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:类型   定义   数据库   需要
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图