
1.7.3 <typeHandlers>标签
<typeHandlers>标签的作用是将传入参数的javaType(Java类型)转换为jdbcType(JDBC类型,对应数据库的数据类型),反之从数据库读出结果(即将jdbcType转换为javaType)。
MyBatis提供了大量默认的内置转换器,可以完成大部分常见的类型转换,但若默认的转换器无法满足要求时,可以自定义转换器。自定义转换器需实现TypeHandler接口或者继承BaseTypeHandler类。创建好后需要进行如下注册:
<typeHandlers>
<typeHandler handler="com.lifeng.utils.MyTypeHandler"/>
</typeHandlers>
其中 handler 属性指定的类 com.lifeng.utils.MyTypeHandler 为自定义的转换器(类),然后<ResultMap>标签中就可以引用这个转换器了。
【注意】上面这段配置代码块必须放在environments前面和typeAliases后面。
自定义转换器实际使用起来比较复杂,还涉及后面的知识点,本书配套资源提供了一个完整项目案例mybatis15供参考,请读者至少学完第2章再回头来学习这个项目案例。
项目案例:复制项目mybatis14为mybatis15,在数据库student表中添加一个列address,类型为VARCHAR,用于存储学生的地址信息,存储地址暂定用“城市,街道”这样的格式。在包com.lifeng.entity下新建一个类Address,用于封装学生的地址信息,该类有city和street两个属性,重写toString()方法,使城市city和街道street以“,”连接,创建带参数的构造方法,输入参数为“城市,街道”格式的字符串,在构造方法中进行拆分,分别给city和street属性赋值。实体类Student中添加一个Address类型的属性address。实现学生信息的查找与添加。
问题分析:数据库中地址列是VARCHAR字符类型,Student类中地址属性是Address对象类型,明显类型不一致,按之前的步骤,是无法正确查询并显示出数据来的,添加数据也一样。所以这里要用到自定义类型转换器,使数据库中的address列的VARCHAR类型能正确地转换映射到Student类的address属性的Address对象类型。(完整代码参见本书配套资源:第1章/typeHandler自定义转换器/mybatis15)
关键步骤如下所示:
package com.lifeng.utils;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import com.lifeng.entity.Address;
public class MyTypeHandler extends BaseTypeHandler<Address> {
@Override
public Address getNullableResult(ResultSet resultSet, String columnName)
throws SQLException {
return new Address(resultSet.getString(columnName));
}
@Override
public Address getNullableResult(ResultSet resultSet, int columnIndex)
throws SQLException {
return new Address(resultSet.getString(columnIndex));
}
@Override
public Address getNullableResult(CallableStatement callableStatement, int columnIndex)
throws SQLException {
return new Address(callableStatement.getString(columnIndex));
}
@Override
public void setNonNullParameter(PreparedStatement preparedStatement, int index,
Address address, JdbcType jdbcType) throws SQLException {
preparedStatement.setString(index, address.toString());
}
}