typeHandler源码分析可参考:http://www.cnblogs.com/dongying/p/4040435.html
typeHandler的作用:可以在bean对象的属性和数据库中存储的对象属性进行转换, 譬如bean中是list属性,存储到数据库中可以是array属性, bean中是java.util.Date属性,数据库中存储的是varchar类型的unix时间戳。
typeHandler 常用的配置为Java类型(javaType),JDBC类型(jdbcType). typeHandler 的作用就是将参数从javaType转化为jdbcType,或者从数据库取出结果时把jdbcType转化成javaType.
typeHandler和别名一样,分为Mybatis系统定义和用户自定义两种. 一般涞水,Mybatis系统定义就可以实现大部分的功能,如果使用用户自定义的typeHandler,我们处理时候务必小心谨慎,以避免不必要的错误.
系统定义的typeHandler
无论是 MyBatis 在预处理语句(PreparedStatement)中设置一个参数时,还是从结果集中取出一个值时,都会用类型处理器将获取的值以合适的方式转换成 Java 类型。Mybatis默认为我们实现了许多TypeHandler, 当我们没有配置指定TypeHandler时,Mybatis会根据参数或者返回结果的不同,默认为我们选择合适的TypeHandler处理。
mybatis中已经提供的有如下:
使用起来其实比较简单,只需要在resultMap中定义转换类型就可以了。表示在获取查询结果生成bean对象的时候,使用org.apache.ibatis.type.DateTypeHandler进行处理。
<mapper namespace="com.wang.MyBatis.model.UserMapper">
<!-- 自定义返回结果集 -->
<resultMap id="userMap" type="com.wang.MyBatis.model.UserBean">
<id property="id" column="id" javaType="java.lang.Integer"></id>
<result property="username" column="username" javaType="java.lang.String"></result>
<result property="password" column="password" javaType="java.lang.String"></result>
<result typeHandler="org.apache.ibatis.type.DateTypeHandler" column="regTime" javaType="java.util.Date"
jdbcType="VARCHAR"
property="regTime"/>
</resultMap>
<insert id="insertUser" useGeneratedKeys="true" keyProperty="id">
insert into t_user_timeStamp (username,password,regTime) values
(#{username},#{password},#{regTime,typeHandler=org.apache.ibatis.type.DateTypeHandler})
</insert>
在插入和更新的时候自定使用
<update id="updateUser" >
update t_user_timeStamp set username=#{username},password=#{password},regTime=
#{regTime,typeHandler=org.apache.ibatis.type.DateTypeHandler} where id=#{id}
</update>
#{regTime,typeHandler=org.apache.ibatis.type.DateTypeHandler}
表示在插入和更新regTime字段时,使用org.apache.ibatis.type.DateTypeHandler进行处理。
自定义typeHandler
配置typeHandler
<configuration>
<typeHandlers>
<!--
当配置package的时候,mybatis会去配置的package扫描TypeHandler
<package name="com.dy.demo"/>
-->
<!-- handler属性直接配置我们要指定的TypeHandler -->
<typeHandler handler=""/>
<!-- javaType 配置java类型,例如String, 如果配上javaType, 那么指定的typeHandler就只作用于指定的类型 -->
<typeHandler javaType="" handler=""/>
<!-- jdbcType 配置数据库基本数据类型,例如varchar, 如果配上jdbcType, 那么指定的typeHandler就只作用于指定的类型 -->
<typeHandler jdbcType="" handler=""/>
<!-- 也可两者都配置 -->
<typeHandler javaType="" jdbcType="" handler=""/>
</typeHandlers>
......
</configuration>
mybatis对于属性转换已经提供了较多的类,如果没有我们所需要的,可以自定义实现一个。属性转换类都实现接口类BaseTypeHandler<T>(package org.apache.ibatis.type;),并且需要实现其中的四个函数:
public abstract void setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException;
public abstract T getNullableResult(ResultSet rs, String columnName) throws SQLException;
public abstract T getNullableResult(ResultSet rs, int columnIndex) throws SQLException;
public abstract T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException;
举例:
将map装换成字符串存储到数据库,取出时将字符串装换成map
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.Map;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.codehaus.jackson.map.ObjectMapper;
import com.winturn.exceptions.RolerServiceException;
import com.winturn.utils.JsonMapUtil;
/**
*
* @ClassName: JsonMapTypeHandler
* @Description: 将map装换成数组存储数据库,取出时将字符串装换成map
* @author sgl
* @date 2015年12月21日 下午6:22:50
*/
public class JsonMapTypeHandler extends BaseTypeHandler<Map<String, Object>> {
ObjectMapper mapper = new ObjectMapper();
@Override
public Map<String, Object> getNullableResult(ResultSet rs, String columnName) {
try {
String value = rs.getString(columnName);
return mapper.readValue(value, Map.class);
} catch (Exception e) {
}
return null;
}
@Override
public Map<String, Object> getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
try {
String value = rs.getString(columnIndex);
return mapper.readValue(value, Map.class);
} catch (Exception e) {
}
return null;
}
@Override
public Map<String, Object> getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
try {
String value = cs.getString(columnIndex);
return mapper.readValue(value, Map.class);
} catch (Exception e) {
}
return null;
}
@Override
public void setNonNullParameter(PreparedStatement ps, int i, Map<String, Object> parameter, JdbcType jdbcType)
throws SQLException {
if (parameter == null) {
ps.setNull(i, Types.VARCHAR);
} else {
try {
ps.setString(i, JsonMapUtil.getJsonStrByMap(parameter));
} catch (RolerServiceException e) {
e.printStackTrace();
}
}
}
}
自定义typeHandler 里用注解配置jdbcType和javaType.这两个注解是:
. @MappedTypes 定义的是javaType类型,可以指定那些java类型被拦截
. @MappedJdbcTypes 定义的是JdbcType类型,它需要满足枚举类org.apache.ibatis.type.JdbcType所列的枚举类型
至此我们还不能测试,我们还需要去标识哪些参数或者结果类型去用typeHandler进行转换,在没有任何标识的情况下,MyBatis是不会启用自定义的typeHandler进行转换结果的,所以还要给予对应的标识,比如配置jdbcType和javaType.,或者直接用typeHandler指定,因此我们需要修改映射器的XML配置.
<mapper namespace="com.wang.MyBatis.model.UserMapper">
<!-- 自定义返回结果集 -->
<resultMap id="userMap" type="com.wang.MyBatis.model.UserBean">
<id property="id" column="id" javaType="java.lang.Integer"></id>
<result property="username" column="username" javaType="java.lang.String"></result>
<result property="password" column="password" javaType="java.lang.String"></result>
<!--定义结果类型转换标识,才能使用类型转化器-->
<result typeHandler="org.apache.ibatis.type.DateTypeHandler" column="regTime" property="regTime"
javaType="java.util.Date" jdbcType="VARCHAR"/>
</resultMap>