一、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,但是一般都在接口实现类上定义。