字段类型处理器
类型处理器,用于 JavaType 与 JdbcType 之间的转换,用于 PreparedStatement 设置参数值和从 ResultSet 或 CallableStatement 中取出一个值,本文讲解 mybaits-plus
内置常用类型处理器如何通过TableField
注解快速注入到 mybatis
容器中。
@Data
@Accessors(chain = true)
@TableName(autoResultMap = true)
public class User {
private Long id;
...
/**
* 注意!! 必须开启映射注解
*
* @TableName(autoResultMap = true)
*
* 以下两种类型处理器,二选一 也可以同时存在
*
* 注意!!选择对应的 JSON 处理器也必须存在对应 JSON 解析依赖包
*/
@TableField(typeHandler = JacksonTypeHandler.class)
// @TableField(typeHandler = FastjsonTypeHandler.class)
private OtherInfo otherInfo;
}
该注解对应了 XML 中写法为
<result column="other_info" jdbcType="VARCHAR" property="otherInfo" typeHandler="com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler" />
实际使用
1,准备工作
(1)MyBatis 中的 TypeHandler 类型处理器用于 JavaType 与 JdbcType 之间的转换,假设我们用户表中有一个联系方式字段,类型为字符串:
![原文:SpringBoot - MyBatis-Plus使用详解16(字段类型处理器TypeHandler)](https://i-blog.csdnimg.cn/blog_migrate/8c45adecd499c1df06623ae3a83718c1.png)
(2)而对应的实体类代码如下,可以看到实体类中 contact 属性类型为 Map。由于与数据库字段类型不匹配,如果不做任何处理的话无论是查询还是插入都会报错。
这里我们通过 @TableField 注解将 FastjsonTypeHandler 这个类型处理器快速注入到 mybatis 容器中:
注意:使用字段类型处理器时,必须开启映射注解 @TableName(autoResultMap = true)。否则插入没问题,但查询时该字段会为空。
1 2 3 4 5 6 7 8 9 10 | @Data @TableName (autoResultMap = true ) public class UserInfo { private Integer id; private String userName; private String passWord; private Integer age; @TableField (typeHandler = FastjsonTypeHandler. class ) private Map<String, String> contact; } |
(3)由于这里用到了 Fastjson 这个 JSON 处理器,所以项目中也要添加相关的依赖:
1 2 3 4 5 | < dependency > < groupId >com.alibaba</ groupId > < artifactId >fastjson</ artifactId > < version >1.2.56</ version > </ dependency > |
2,开始测试
(1)首先创建一个对象插入到数据库,可以看到虽然对象里的 contact 是一个 Map,但会自动转成 JSON 字符串存到数据库中:
1 2 3 4 5 6 7 8 9 | UserInfo user = new UserInfo(); user.setUserName( "hangge" ); user.setPassWord( "123" ); //添加联系方式 Map<String, String> contact = new HashMap<>(); contact.put( "phone" , "010-1234567" ); contact.put( "tel" , "13388889999" ); user.setContact(contact); userInfoMapper.insert(user); |
![原文:SpringBoot - MyBatis-Plus使用详解16(字段类型处理器TypeHandler)](https://i-blog.csdnimg.cn/blog_migrate/ba769057f38685439f073f0dc54514af.jpeg)
(2)接着测试下查询,可以发现数据库的 JSON 字符串也会自动转换成 Map:
1 2 | List<UserInfo> users = userInfoMapper.selectList( null ); System.out.println(users); |
![原文:SpringBoot - MyBatis-Plus使用详解16(字段类型处理器TypeHandler)](https://i-blog.csdnimg.cn/blog_migrate/d9d5289a86c294e4820515aa1154bc7f.jpeg)
附:自定义 TypeHandler 类型处理器
1,准备工作
(1)如果我们需要实现一个自定义的 TypeHandler 类型处理器,则需继承 ListTypeHandler 接口,接口作用是用于指定 jdbc 与 java 的数据类型间对应关系处理。接口代码如下:
1 2 3 4 5 6 7 8 | public interface TypeHandler<T> { // 保存操作,数据入库之前时数据处理 void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException; //下面三个则是,从数据库加载数据后,vo对象封装前的数据处理 T getResult(ResultSet rs, String columnName) throws SQLException; T getResult(ResultSet rs, int columnIndex) throws SQLException; T getResult(CallableStatement cs, int columnIndex) throws SQLException; } |
(2)这里我们定义一个 list 类型转 varchar(逗号隔开的字符串)的类型处理器,即 list [1,2,3] ==》varchar 1,2,3
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | @MappedJdbcTypes (JdbcType.VARCHAR) //数据库类型 @MappedTypes ({List. class }) //java数据类型 @Log public class ListTypeHandler implements TypeHandler<List<String>> { @Override public void setParameter(PreparedStatement ps, int i, List<String> parameter, JdbcType jdbcType) throws SQLException { log.info( "method ====>>> setParameter" ); String hobbys = dealListToOneStr(parameter); ps.setString(i , hobbys); } /** * 集合拼接字符串 * @param parameter * @return */ private String dealListToOneStr(List<String> parameter){ if (parameter == null || parameter.size() <= 0 ) return null ; String res = "" ; for ( int i = 0 ;i < parameter.size(); i++) { if (i == parameter.size()- 1 ){ res+=parameter.get(i); return res; } res+=parameter.get(i)+ "," ; } return null ; } @Override public List<String> getResult(ResultSet rs, String columnName) throws SQLException { log.info( "method ====>>> getResult(ResultSet rs, String columnName)" ); return Arrays.asList(rs.getString(columnName).split( "," )); } @Override public List<String> getResult(ResultSet rs, int columnIndex) throws SQLException { log.info( "method ====>>> getResult(ResultSet rs, int columnIndex)" ); return Arrays.asList(rs.getString(columnIndex).split( "," )); } @Override public List<String> getResult(CallableStatement cs, int columnIndex) throws SQLException{ log.info( "method ====>>> getResult(CallableStatement cs, int columnIndex)" ); String hobbys = cs.getString(columnIndex); return Arrays.asList(hobbys.split( "," )); } } |
(3)接着在对应的实例类中使用 @TableField 注解指定使用这个自定义的字段类型处理器:
1 2 3 4 5 6 7 8 9 10 | @Data @TableName (autoResultMap = true ) public class UserInfo { private Integer id; private String userName; private String passWord; private Integer age; @TableField (typeHandler = ListTypeHandler. class ) private List<String> contact; } |
2,开始测试
(1)首先创建一个对象插入到数据库,可以看到虽然对象里的 contact 是一个 List,但会自动转成逗号隔开的字符串存到数据库中:
1 2 3 4 5 6 7 8 9 10 | UserInfo user = new UserInfo(); user.setUserName( "hangge" ); user.setPassWord( "123" ); //添加联系方式 List<String> contact = new ArrayList<>(); contact.add( "010-1234567" ); contact.add( "13388889999" ); contact.add( "10001" ); user.setContact(contact); userInfoMapper.insert(user); |
![原文:SpringBoot - MyBatis-Plus使用详解16(字段类型处理器TypeHandler)](https://i-blog.csdnimg.cn/blog_migrate/53d6a5fff20b9d077310a8247a92587d.jpeg)
(2)接着测试下查询,可以发现数据库的字符串也会自动还原成 List:
1 2 | List<UserInfo> users = userInfoMapper.selectList( null ); System.out.println(users); |
![原文:SpringBoot - MyBatis-Plus使用详解16(字段类型处理器TypeHandler)](https://i-blog.csdnimg.cn/blog_migrate/ee6d2217b47a59f48f87d996e4907c62.jpeg)
原文出自:www.hangge.com 转载请保留原文链接:https://www.hangge.com/blog/cache/detail_2926.html