MyBatis-Plus——字段类型处理器TypeHandler

x33g5p2x  于2022-05-27 转载在 其他  
字(4.0k)|赞(0)|评价(0)|浏览(1014)

字段类型处理器(TypeHandler)

1,准备工作

(1)MyBatis 中的 TypeHandler 类型处理器用于 JavaTypeJdbcType 之间的转换,假设我们用户表中有一个联系方式字段,类型为字符串:

(2)而对应的实体类代码如下,可以看到实体类中 contact 属性类型为 Map。由于与数据库字段类型不匹配,如果不做任何处理的话无论是查询还是插入都会报错。

这里我们通过 @TableField 注解将 FastjsonTypeHandler 这个类型处理器快速注入到 mybatis 容器中:
注意:使用字段类型处理器时,必须开启映射注解 @TableName(autoResultMap = true)。否则插入没问题,但查询时该字段会为空。

  1. @Data
  2. @TableName(autoResultMap = true)
  3. public class UserInfo {
  4. private Integer id;
  5. private String userName;
  6. private String passWord;
  7. private Integer age;
  8. @TableField(typeHandler = FastjsonTypeHandler.class)
  9. private Map<String, String> contact;
  10. }

(3)由于这里用到了 Fastjson 这个JSON 处理器,所以项目中也要添加相关的依赖:

  1. <dependency>
  2. <groupId>com.alibaba</groupId>
  3. <artifactId>fastjson</artifactId>
  4. <version>1.2.56</version>
  5. </dependency>

2,开始测试

(1)首先创建一个对象插入到数据库,可以看到虽然对象里的 contact 是一个 Map,但会自动转成 JSON 字符串存到数据库中:

  1. UserInfo user = new UserInfo();
  2. user.setUserName("hangge");
  3. user.setPassWord("123");
  4. //添加联系方式
  5. Map<String, String> contact = new HashMap<>();
  6. contact.put("phone", "010-1234567");
  7. contact.put("tel", "13388889999");
  8. user.setContact(contact);
  9. userInfoMapper.insert(user);

(2)接着测试下查询,可以发现数据库的 字符串也会自动转换成 :

  1. List<UserInfo> users = userInfoMapper.selectList(null);
  2. System.out.println(users);

附:自定义 TypeHandler 类型处理器

1,准备工作

(1)如果我们需要实现一个自定义的 TypeHandler 类型处理器,则需继承 ListTypeHandler 接口,接口作用是用于指定 jdbcjava 的数据类型间对应关系处理。接口代码如下:

  1. public interface TypeHandler<T> {
  2. // 保存操作,数据入库之前时数据处理
  3. void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException;
  4. //下面三个则是,从数据库加载数据后,vo对象封装前的数据处理
  5. T getResult(ResultSet rs, String columnName) throws SQLException;
  6. T getResult(ResultSet rs, int columnIndex) throws SQLException;
  7. T getResult(CallableStatement cs, int columnIndex) throws SQLException;
  8. }

(2)这里我们定义一个 list类型转varchar (逗号隔开的字符串)的类型处理器,即 list [1,2,3] ==》varchar 1,2,3

  1. @MappedJdbcTypes(JdbcType.VARCHAR) //数据库类型
  2. @MappedTypes({List.class}) //java数据类型
  3. @Log
  4. public class ListTypeHandler implements TypeHandler<List<String>> {
  5. @Override
  6. public void setParameter(PreparedStatement ps, int i,
  7. List<String> parameter, JdbcType jdbcType) throws SQLException {
  8. log.info("method ====>>> setParameter");
  9. String hobbys = dealListToOneStr(parameter);
  10. ps.setString(i , hobbys);
  11. }
  12. /**
  13. * 集合拼接字符串
  14. * @param parameter
  15. * @return
  16. */
  17. private String dealListToOneStr(List<String> parameter){
  18. if(parameter == null || parameter.size() <=0)
  19. return null;
  20. String res = "";
  21. for (int i = 0 ;i < parameter.size(); i++) {
  22. if(i == parameter.size()-1){
  23. res+=parameter.get(i);
  24. return res;
  25. }
  26. res+=parameter.get(i)+",";
  27. }
  28. return null;
  29. }
  30. @Override
  31. public List<String> getResult(ResultSet rs, String columnName)
  32. throws SQLException {
  33. log.info("method ====>>> getResult(ResultSet rs, String columnName)");
  34. return Arrays.asList(rs.getString(columnName).split(","));
  35. }
  36. @Override
  37. public List<String> getResult(ResultSet rs, int columnIndex)
  38. throws SQLException {
  39. log.info("method ====>>> getResult(ResultSet rs, int columnIndex)");
  40. return Arrays.asList(rs.getString(columnIndex).split(","));
  41. }
  42. @Override
  43. public List<String> getResult(CallableStatement cs, int columnIndex) throws SQLException{
  44. log.info("method ====>>> getResult(CallableStatement cs, int columnIndex)");
  45. String hobbys = cs.getString(columnIndex);
  46. return Arrays.asList(hobbys.split(","));
  47. }
  48. }

(3)接着在对应的实例类中使用@TableField 注解指定使用这个自定义的字段类型处理器:

  1. @Data
  2. @TableName(autoResultMap = true)
  3. public class UserInfo {
  4. private Integer id;
  5. private String userName;
  6. private String passWord;
  7. private Integer age;
  8. @TableField(typeHandler = ListTypeHandler.class)
  9. private List<String> contact;
  10. }

2,开始测试

(1)首先创建一个对象插入到数据库,可以看到虽然对象里的 contact****List,但会自动转成逗号隔开的字符串存到数据

  1. UserInfo user = new UserInfo();
  2. user.setUserName("hangge");
  3. user.setPassWord("123");
  4. //添加联系方式
  5. List<String> contact = new ArrayList<>();
  6. contact.add("010-1234567");
  7. contact.add("13388889999");
  8. contact.add("10001");
  9. user.setContact(contact);
  10. userInfoMapper.insert(user);

(2)接着测试下查询,可以发现数据库的字符串也会自动还原成 List:

  1. List<UserInfo> users = userInfoMapper.selectList(null);
  2. System.out.println(users);

相关文章