前言:直入正题,在咱们利用mybatis做为持久层框架存储数据时,从mybatis接收参数到mysql存储数据,都会用到typeHandler类型处理器。这也就是从JavaType->JdbcType的转化过程。因为mybatis初始时已经内置大部分基础类型转化的TypeHandler,已经足够咱们日常的简单应用开发了,因此大多数状况下并不须要咱们本身去定义类型转换器。可是,当遇到一些特殊状况时,为了开发的方便性,咱们才回去自定义一些类型转换器。java
使用场景:mybatis在预处理语句(PreparedStatement)中设置一个参数时,或者从结果集(ResultSet)中取出一个值时,都会用到TypeHandler。它的做用就是将java类型(javaType)转化为jdbc类型(jdbcType),或者将jdbc类型(jdbcType)转化为java类型(javaType)。mysql
mybatis初始内置TypeHandler:git
public TypeHandlerRegistry() {
this.register((Class)Boolean.class, (TypeHandler)(new BooleanTypeHandler()));
this.register((Class)Boolean.TYPE, (TypeHandler)(new BooleanTypeHandler()));
this.register((JdbcType)JdbcType.BOOLEAN, (TypeHandler)(new BooleanTypeHandler()));
this.register((JdbcType)JdbcType.BIT, (TypeHandler)(new BooleanTypeHandler()));
this.register((Class)Byte.class, (TypeHandler)(new ByteTypeHandler()));
this.register((Class)Byte.TYPE, (TypeHandler)(new ByteTypeHandler()));
this.register((JdbcType)JdbcType.TINYINT, (TypeHandler)(new ByteTypeHandler()));
this.register((Class)Short.class, (TypeHandler)(new ShortTypeHandler()));
this.register((Class)Short.TYPE, (TypeHandler)(new ShortTypeHandler()));
this.register((JdbcType)JdbcType.SMALLINT, (TypeHandler)(new ShortTypeHandler()));
this.register((Class)Integer.class, (TypeHandler)(new IntegerTypeHandler()));
this.register((Class)Integer.TYPE, (TypeHandler)(new IntegerTypeHandler()));
this.register((JdbcType)JdbcType.INTEGER, (TypeHandler)(new IntegerTypeHandler()));
this.register((Class)Long.class, (TypeHandler)(new LongTypeHandler()));
this.register((Class)Long.TYPE, (TypeHandler)(new LongTypeHandler()));
this.register((Class)Float.class, (TypeHandler)(new FloatTypeHandler()));
this.register((Class)Float.TYPE, (TypeHandler)(new FloatTypeHandler()));
this.register((JdbcType)JdbcType.FLOAT, (TypeHandler)(new FloatTypeHandler()));
this.register((Class)Double.class, (TypeHandler)(new DoubleTypeHandler()));
this.register((Class)Double.TYPE, (TypeHandler)(new DoubleTypeHandler()));
this.register((JdbcType)JdbcType.DOUBLE, (TypeHandler)(new DoubleTypeHandler()));
this.register((Class)Reader.class, (TypeHandler)(new ClobReaderTypeHandler()));
this.register((Class)String.class, (TypeHandler)(new StringTypeHandler()));
this.register((Class)String.class, JdbcType.CHAR, (TypeHandler)(new StringTypeHandler()));
this.register((Class)String.class, JdbcType.CLOB, (TypeHandler)(new ClobTypeHandler()));
this.register((Class)String.class, JdbcType.VARCHAR, (TypeHandler)(new StringTypeHandler()));
this.register((Class)String.class, JdbcType.LONGVARCHAR, (TypeHandler)(new ClobTypeHandler()));
this.register((Class)String.class, JdbcType.NVARCHAR, (TypeHandler)(new NStringTypeHandler()));
this.register((Class)String.class, JdbcType.NCHAR, (TypeHandler)(new NStringTypeHandler()));
this.register((Class)String.class, JdbcType.NCLOB, (TypeHandler)(new NClobTypeHandler()));
this.register((JdbcType)JdbcType.CHAR, (TypeHandler)(new StringTypeHandler()));
this.register((JdbcType)JdbcType.VARCHAR, (TypeHandler)(new StringTypeHandler()));
this.register((JdbcType)JdbcType.CLOB, (TypeHandler)(new ClobTypeHandler()));
this.register((JdbcType)JdbcType.LONGVARCHAR, (TypeHandler)(new ClobTypeHandler()));
this.register((JdbcType)JdbcType.NVARCHAR, (TypeHandler)(new NStringTypeHandler()));
this.register((JdbcType)JdbcType.NCHAR, (TypeHandler)(new NStringTypeHandler()));
this.register((JdbcType)JdbcType.NCLOB, (TypeHandler)(new NClobTypeHandler()));
this.register((Class)Object.class, JdbcType.ARRAY, (TypeHandler)(new ArrayTypeHandler()));
this.register((JdbcType)JdbcType.ARRAY, (TypeHandler)(new ArrayTypeHandler()));
this.register((Class)BigInteger.class, (TypeHandler)(new BigIntegerTypeHandler()));
this.register((JdbcType)JdbcType.BIGINT, (TypeHandler)(new LongTypeHandler()));
this.register((Class)BigDecimal.class, (TypeHandler)(new BigDecimalTypeHandler()));
this.register((JdbcType)JdbcType.REAL, (TypeHandler)(new BigDecimalTypeHandler()));
this.register((JdbcType)JdbcType.DECIMAL, (TypeHandler)(new BigDecimalTypeHandler()));
this.register((JdbcType)JdbcType.NUMERIC, (TypeHandler)(new BigDecimalTypeHandler()));
this.register((Class)InputStream.class, (TypeHandler)(new BlobInputStreamTypeHandler()));
this.register((Class)Byte[].class, (TypeHandler)(new ByteObjectArrayTypeHandler()));
this.register((Class)Byte[].class, JdbcType.BLOB, (TypeHandler)(new BlobByteObjectArrayTypeHandler()));
this.register((Class)Byte[].class, JdbcType.LONGVARBINARY, (TypeHandler)(new BlobByteObjectArrayTypeHandler()));
this.register((Class)byte[].class, (TypeHandler)(new ByteArrayTypeHandler()));
this.register((Class)byte[].class, JdbcType.BLOB, (TypeHandler)(new BlobTypeHandler()));
this.register((Class)byte[].class, JdbcType.LONGVARBINARY, (TypeHandler)(new BlobTypeHandler()));
this.register((JdbcType)JdbcType.LONGVARBINARY, (TypeHandler)(new BlobTypeHandler()));
this.register((JdbcType)JdbcType.BLOB, (TypeHandler)(new BlobTypeHandler()));
this.register(Object.class, this.UNKNOWN_TYPE_HANDLER);
this.register(Object.class, JdbcType.OTHER, this.UNKNOWN_TYPE_HANDLER);
this.register(JdbcType.OTHER, this.UNKNOWN_TYPE_HANDLER);
this.register((Class)Date.class, (TypeHandler)(new DateTypeHandler()));
this.register((Class)Date.class, JdbcType.DATE, (TypeHandler)(new DateOnlyTypeHandler()));
this.register((Class)Date.class, JdbcType.TIME, (TypeHandler)(new TimeOnlyTypeHandler()));
this.register((JdbcType)JdbcType.TIMESTAMP, (TypeHandler)(new DateTypeHandler()));
this.register((JdbcType)JdbcType.DATE, (TypeHandler)(new DateOnlyTypeHandler()));
this.register((JdbcType)JdbcType.TIME, (TypeHandler)(new TimeOnlyTypeHandler()));
this.register((Class)java.sql.Date.class, (TypeHandler)(new SqlDateTypeHandler()));
this.register((Class)Time.class, (TypeHandler)(new SqlTimeTypeHandler()));
this.register((Class)Timestamp.class, (TypeHandler)(new SqlTimestampTypeHandler()));
上面都是mybatis内置的处理器,因此在平时开发的时候咱们不用去关心java到数据库的类型转化关系,mybatis都帮咱们把这些工做完成了。但这并非咱们要关心的重点,咱们须要的是自定义TypeHandler去应对更多的需求。web
对TypeHandler接口的一些说明:sql
TypeHandler是一个接口,它定义了以下四个方法,实现类必须去实现,方法以下:数据库
void setParameter(PreparedStatement var1, int var2, T var3, JdbcType var4) throws SQLException;
T getResult(ResultSet var1, String var2) throws SQLException;
T getResult(ResultSet var1, int var2) throws SQLException;
T getResult(CallableStatement var1, int var2) throws SQLException;
}
setParameter:经过preparedStatement对象设置参数,将T类型的数据存入数据库。apache
getResult:经过列名或者下标来获取结果数据,也能够经过CallableStatement获取数据。mybatis
自定义注解里还能够经过注解配置java类型和jdbc类型:
@MappedTypes() :注解配置java类型
@MappedJdbcTypes(): 注解配置jdbc类型app
枚举类型的TypeHandler:
EnumOrdinalTypeHandler:使用枚举字符串名称做为参数传递。
EnumTypeHandler:使用整数下标做为参数传递。框架
为了实现自定义枚举类型的TypeHandler,咱们经过性别(Sex)类型来进行演示:
首先定义Sex类型的枚举,定义以下:
package com.cbg.Entity;
/** * Created by chenboge on 2017/5/18. * <p> * Email:baigegechen@gmail.com * <p> * description: */
//用于SexTypeHandler的性别转换器枚举
public enum Sex {
//每个类型都是一个枚举类(Sex)的实例
MALE(0, "男"),
FMALE(1, "女");
//用于保存在数据库
private int SexCode;
//用于UI展现
private String SexName;
Sex(int sexCode, String sexName) {
SexCode = sexCode;
SexName = sexName;
}
public int getSexCode() {
return SexCode;
}
//经过SexCode的值来获取Sex枚举类型,数据库只需保存code,经过代码解析成Sex类型
public static Sex getSexFromCode(int code) {
for (Sex sex : Sex.values()) {
if (sex.getSexCode() == code) {
return sex;
}
}
return null;
}
}
若是咱们不自定义TypeHandler,也能够经过mybatis内置的EnumOrdinalTypeHandler来进行类型转换,在mapper文件中的resultmap中进行以下配置:
<result property="sex" column="sex" typeHandler="org.apache.ibatis.type.EnumOrdinalTypeHandler"/>
自定义枚举TypeHandler:
package com.cbg.handler;
import com.cbg.Entity.Sex;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.TypeHandler;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/** * Created by chenboge on 2017/5/18. * <p> * Email:baigegechen@gmail.com * <p> * description: */
public class SexTypeHandler implements TypeHandler<Sex> {
@Override
public void setParameter(PreparedStatement preparedStatement, int i, Sex sex, JdbcType jdbcType) throws SQLException {
//设置第i个参数的值为传入sex的code值,preparedStatement为执行数据库操纵的对象
//传值的时候是一个sex对象,可是当进行映射插入的时候就会转化为sex的code值进行存储
preparedStatement.setInt(i, sex.getSexCode());
}
@Override
public Sex getResult(ResultSet resultSet, String s) throws SQLException {
//获取数据库存储的sex的code值
int result = resultSet.getInt(s);
return Sex.getSexFromCode(result);
}
@Override
public Sex getResult(ResultSet resultSet, int i) throws SQLException {
int result = resultSet.getInt(i);
return Sex.getSexFromCode(result);
}
@Override
public Sex getResult(CallableStatement callableStatement, int i) throws SQLException {
int result = callableStatement.getInt(i);
return Sex.getSexFromCode(result);
}
}
最后须要在配置文件中运用咱们自定义的TypeHandler对Sex进行类型转换:
<resultMap id="userMap" type="com.cbg.pojo.UserBean">
<result property="id" column="id"/>
<result property="userName" column="user_name"/>
<result property="birthday" column="birthday"/>
<result property="mobile" column="mobile"/>
<result property="email" column="email"/>
<result property="note" column="note"/>
<result property="sex" column="sex" javaType="com.cbg.Entity.Sex" jdbcType="INTEGER"
typeHandler="com.cbg.handler.SexTypeHandler"/>
</resultMap>
经过上面的配置,自定义的TypeHandler就会生效,对java中的Sex对象和数据库中的Integer进行自定转换。数据库只需存储Sex的code值,获取数据库数据时自动转化为Sex枚举对象,使用至关方便,也更加灵活。
总结:自定义TypeHandler整体上来讲仍是比较简单的。还有不清楚的同窗能够移步:ssm基础框架整合+自定义枚举TypeHandler进行查看。