Mybatis从入门到精通——TypeHandler的使用(18)

一、TypeHandler

TypeHandler是Mybatis提供的一个JdcbType和JavaType之间互相转换的处理器,用于在传参和返回值设置时进行转换,使用在result、id这类返回值映射标签上,一般不需要进行转换,因为Mybatis已经提供了足够多且常用的TypeHandler。

 

二、案例

案例说明:

对于枚举的转换,Mybatis是没有提供的,我们需要把数据库中sex性别的1和0转换为枚举并设值到对应属性中。

User实体类:

public class User {
    private Integer id;

    private String userName;

    private String realName;

    private Sex sex;

    private String mobile;

    private String email;

    private String note;

    private Integer positionId;
}

Sex枚举类:

public enum Sex {

  MALE(1, "男"),
  FEMALE(0, "女");

  Sex(int id, String name) {
    this.id = id;
    this.name = name;
  }

  private int id;
  private String name;

  public static Sex getSexById(int id) {
    for (Sex sex : Sex.values()) {
      if (sex.getId() == id) {
        return sex;
      }
    }
    return null;
  }

  public int getId() {
    return id;
  }

  public void setId(int id) {
    this.id = id;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  @Override
  public String toString() {
    return "Sex{" +
      "id=" + id +
      ", name='" + name + '\'' +
      '}';
  }
}

TypeHandler实现类:

@MappedJdbcTypes({JdbcType.CHAR,JdbcType.VARCHAR})
@MappedTypes(Sex.class)
public class SexTypeHandler extends BaseTypeHandler<Sex> {

    /**
     * 参数设置
     * @param ps Statement
     * @param i 参数位置
     * @param parameter 参数
     * @param jdbcType jdbc类型
     * @throws SQLException
     */
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, Sex parameter, JdbcType jdbcType) throws SQLException {
        Integer sex = parameter.getId();
        ps.setString(i,sex.toString());
    }

    /**
     * 返回值处理
     * @param rs ResultSet结果集
     * @param columnName 当前列名
     * @return Sex
     * @throws SQLException
     */
    @Override
    public Sex getNullableResult(ResultSet rs, String columnName) throws SQLException {
        Integer id = Integer.valueOf(rs.getString(columnName));
        return Sex.getSexById(id);
    }

    /**
     * 返回值处理
     * @param rs 结果集
     * @param columnIndex 当前需要转为的列的位置
     * @return Sex
     * @throws SQLException
     */
    @Override
    public Sex getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        Integer id = Integer.valueOf(rs.getInt(columnIndex));
        return Sex.getSexById(id);
    }

    /**
     * 存储过程结果处理
     * @param cs
     * @param columnIndex 列的位置
     * @return 映射到属性上的值
     * @throws SQLException
     */
    @Override
    public Sex getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        Integer id = Integer.valueOf(cs.getInt(columnIndex));
        return Sex.getSexById(id);
    }
}

mapper映射文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.my.mapper.UserMapper">

  <resultMap id="BaseResultMap" type="com.my.entity.User">
    <id column="id" jdbcType="INTEGER" property="id" />
    <result column="user_name" jdbcType="VARCHAR" property="userName" />
    <result column="real_name" jdbcType="VARCHAR" property="realName" />
    <!--  typeHandler指明使用的类型转换器,也可以不写会根据属性声明查找  -->
    <result column="sex" jdbcType="CHAR" property="sex" typeHandler="com.my.typehandler.SexTypeHandler"/>
    <result column="mobile" jdbcType="VARCHAR" property="mobile" />
    <result column="email" jdbcType="VARCHAR" property="email" />
    <result column="note" jdbcType="VARCHAR" property="note" />
    <result column="position_id" jdbcType="INTEGER" property="positionId" />
  </resultMap>

  <sql id="Base_Column_List">
    id, user_name, real_name, sex, mobile, email, note, position_id
  </sql>

  <select id="selectBySex" resultMap="BaseResultMap" parameterType="com.my.enums.Sex">
    select
    <include refid="Base_Column_List" />
    from user
    where sex = #{sex}
  </select>
</mapper>

Mybatis配置文件:

    <typeHandlers>
<!--    可以在typeHandler标签上写javaType和jdbcType    -->
<!--        <typeHandler handler="com.my.typehandler.SexTypeHandler" javaType="com.my.enums.Sex" jdbcType="CHAR"></typeHandler>-->
                <typeHandler handler="com.my.typehandler.SexTypeHandler"></typeHandler>
    </typeHandlers>

测试代码:

public class MybatisTest {

    private SqlSessionFactory sqlSessionFactory;

    @Before
    public void init() throws IOException {
        String resource = "mybatis-config.xml";
        //1.使用mybatis的工具读取配置文件
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        //2.创建sqlSessionFactory
        sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
        inputStream.close();
    }

    /**
     * 测试TypeHandler
     */
    @Test
    public void testTypeHandler() {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        List<User> users = userMapper.selectBySex(Sex.FEMALE);
        System.out.println(users);
        sqlSession.close();
    }

}

 

三、使用步骤

步骤:

1.继承BaseTypeHandler<T>类或实现TypeHandler<T>接口,一般继承BaseTypeHandler<T>类,泛型T指的是要转换的java类型

2.重写4个方法,下文对其进行说明

3.在Mybatis配置文件中注册TypeHandler

4.在其接口实现类上添加@MappedJdbcTypes注解和@MappedTypes注解说明转换的javaType和jdbcType

 

BaseTypeHandler<T>重写方法说明:

1..void setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType):

    该方法在属性设置时调用,当传入的方法参数类型是T时,怎么进行转换处理,i为列号

2.T getNullableResult(ResultSet rs, String columnName):

    该方法在返回值为属性设置时调用,当返回值属性类型为T时,且jdbc类型符合,怎么进行转换处理,columnName为列名

3.T getNullableResult(ResultSet rs, int columnIndex):

    该方法在返回值为属性设置时调用,当返回值属性类型为T时,且jdbc类型符合,怎么进行转换处理,columnName为列号

4.T getNullableResult(CallableStatement cs, int columnIndex):

    该方法在返回值为属性设置时调用,当返回值属性类型为T时,且jdbc类型符合,怎么进行转换处理,columnName为列号 ,该方法为处理存储过程的操作。

 

@MappedJdbcTypes说明

该注解用在TypeHandler<T>实现类上,指明和其进行转换的JDBC类型,可以写多个。

 

@MappedTypes说明

该注解用在TypeHandler<T>实现类上,指明需要转换的Java类型,一般只写一个。

 

四、补充说明

1.BaseTypeHandler<T>类也实现了TypeHandler<T>接口,并做了一些封装,自定义类型转换器继承该类即可。

2.id、result标签中的typeHandler属性可有可无,因为它会根据属性声明类型进行查找。

3.在Mybatis的配置文件中注册类型转换器时,可以定义好javaType和jdbcType,但是一般都在接口实现类上定义。

 

发布了61 篇原创文章 · 获赞 81 · 访问量 10万+

猜你喜欢

转载自blog.csdn.net/m0_37914588/article/details/104757034