MyBatis-Plus(十六)字段类型处理器TypeHandler

字段类型处理器TypeHandler

1、准备工作

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

在这里插入图片描述

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

    这里我们通过 @TableField 注解将 FastjsonTypeHandler 这个类型处理器快速注入到 mybatis 容器中:

注意:使用字段类型处理器时,必须开启映射注解 @TableName(autoResultMap = true)。否则插入没问题,但查询时该字段会为空。

@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;
}
  1. 由于这里用到了 Fastjson 这个 JSON 处理器,所以项目中也要添加相关的依赖:
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.56</version>
</dependency>
  1. 查看数据库,可以发现 mybatis原生默认是以枚举的名称 Enum.name()作为默认值(即 GenderEnum.MALE.name() 和 GenderEnum.FEMALE.name())。这样就要求对应数据库的字段必须是一个varchar类型,这显然不太合适。

在这里插入图片描述

2、开始测试

  1. 首先创建一个对象插入到数据库,可以看到虽然对象里的 contact 是一个 Map,但会自动转成 JSON 字符串存到数据库中:
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);

在这里插入图片描述

  1. 接着测试下查询,可以发现数据库的 JSON 字符串也会自动转换成 Map
List<UserInfo> users = userInfoMapper.selectList(null);
System.out.println(users);

在这里插入图片描述

3、自定义 TypeHandler 类型处理器

  1. 如果我们需要实现一个自定义的 TypeHandler 类型处理器,则需继承 ListTypeHandler 接口,接口作用是用于指定 jdbcjava 的数据类型间对应关系处理。接口代码如下:
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;
}
  1. 这里我们定义一个 list 类型转 varchar(逗号隔开的字符串)的类型处理器,即 list [1,2,3] ==》varchar 1,2,3
@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(","));
    }
}
  1. 接着在对应的实例类中使用 @TableField 注解指定使用这个自定义的字段类型处理器:
@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;
}

点击跳转至原文地址

--------------最后感谢大家的阅读,愿大家技术越来越流弊!--------------

在这里插入图片描述

--------------也希望大家给我点支持,谢谢各位大佬了!!!--------------

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值