类型处理器(typeHandlers)
无论是 MyBatis 在预处理语句(PreparedStatement)中设置一个参数时,还是从结果集中取出一个值时, 都会用类型处理器将获取的值以合适的方式转换成 Java 类型。下表描述了一些默认的类型处理器。
提示 从 3.4.5 开始,MyBatis 默认支持 JSR-310(日期和时间 API)。
类型处理器 | Java 类型 | JDBC 类型 |
---|---|---|
BooleanTypeHandler | java.lang.Boolean , boolean | 数据库兼容的 BOOLEAN |
ByteTypeHandler | java.lang.Byte , byte | 数据库兼容的 NUMERIC 或 BYTE |
ShortTypeHandler | java.lang.Short , short | 数据库兼容的 NUMERIC 或 SMALLINT |
IntegerTypeHandler | java.lang.Integer , int | 数据库兼容的 NUMERIC 或 INTEGER |
LongTypeHandler | java.lang.Long , long | 数据库兼容的 NUMERIC 或 BIGINT |
FloatTypeHandler | java.lang.Float , float | 数据库兼容的 NUMERIC 或 FLOAT |
DoubleTypeHandler | java.lang.Double , double | 数据库兼容的 NUMERIC 或 DOUBLE |
BigDecimalTypeHandler | java.math.BigDecimal | 数据库兼容的 NUMERIC 或 DECIMAL |
StringTypeHandler | java.lang.String | CHAR , VARCHAR |
ClobReaderTypeHandler | java.io.Reader | - |
ClobTypeHandler | java.lang.String | CLOB , LONGVARCHAR |
NStringTypeHandler | java.lang.String | NVARCHAR , NCHAR |
NClobTypeHandler | java.lang.String | NCLOB |
BlobInputStreamTypeHandler | java.io.InputStream | - |
ByteArrayTypeHandler | byte[] | 数据库兼容的字节流类型 |
BlobTypeHandler | byte[] | BLOB , LONGVARBINARY |
DateTypeHandler | java.util.Date | TIMESTAMP |
DateOnlyTypeHandler | java.util.Date | DATE |
TimeOnlyTypeHandler | java.util.Date | TIME |
SqlTimestampTypeHandler | java.sql.Timestamp | TIMESTAMP |
SqlDateTypeHandler | java.sql.Date | DATE |
SqlTimeTypeHandler | java.sql.Time | TIME |
ObjectTypeHandler | Any | OTHER 或未指定类型 |
EnumTypeHandler | Enumeration Type | VARCHAR 或任何兼容的字符串类型,用以存储枚举的名称(而不是索引值) |
EnumOrdinalTypeHandler | Enumeration Type | 任何兼容的 NUMERIC 或 DOUBLE 类型,存储枚举的序数值(而不是名称)。 |
SqlxmlTypeHandler | java.lang.String | SQLXML |
InstantTypeHandler | java.time.Instant | TIMESTAMP |
LocalDateTimeTypeHandler | java.time.LocalDateTime | TIMESTAMP |
LocalDateTypeHandler | java.time.LocalDate | DATE |
LocalTimeTypeHandler | java.time.LocalTime | TIME |
OffsetDateTimeTypeHandler | java.time.OffsetDateTime | TIMESTAMP |
OffsetTimeTypeHandler | java.time.OffsetTime | TIME |
ZonedDateTimeTypeHandler | java.time.ZonedDateTime | TIMESTAMP |
YearTypeHandler | java.time.Year | INTEGER |
MonthTypeHandler | java.time.Month | INTEGER |
YearMonthTypeHandler | java.time.YearMonth | VARCHAR 或 LONGVARCHAR |
JapaneseDateTypeHandler | java.time.chrono.JapaneseDate | DATE |
自定义typeHandler的方式:实现 org.apache.ibatis.type.TypeHandler
接口或者 继承org.apache.ibatis.type.BaseTypeHandler
类。
案例:
字段 | JavaBean | 数据库 |
---|---|---|
time1 | Date | date |
time2 | String | date |
time3 | Date | varchar |
1、编写自定义typeHandler类。采用继承BaseTypeHandler
类
package com.zm.config;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* @Auther: zhangmo
* @Email : zhangmowx@163.com
* @Date: 2019/12/13 20:38
* @Description:
*/
public class MyDateTypeHandler extends BaseTypeHandler {
@Override
public void setNonNullParameter(PreparedStatement ps, int i, Object o, JdbcType jdbcType) throws SQLException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
ps.setString(i, sdf.format((Date) o));
}
@Override
public Object getNullableResult(ResultSet resultSet, String s) throws SQLException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String columnValue = resultSet.getString(s);
if (null != columnValue) {
try {
return sdf.parse(columnValue);
} catch (ParseException e) {
e.printStackTrace();
}
}
return null;
}
@Override
public Object getNullableResult(ResultSet resultSet, int i) throws SQLException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String columnValue = resultSet.getString(i);
if (null != columnValue) {
try {
return sdf.parse(columnValue);
} catch (ParseException e) {
e.printStackTrace();
}
}
return null;
}
@Override
public Object getNullableResult(CallableStatement callableStatement, int i) throws SQLException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String columnValue = callableStatement.getString(i);
if (null != columnValue) {
try {
return sdf.parse(columnValue);
} catch (ParseException e) {
e.printStackTrace();
}
}
return null;
}
}
-
配置typeHandler
<typeHandlers> <typeHandler handler="com.zm.config.MyDateTypeHandler" javaType="Date" jdbcType="VARCHAR"/> </typeHandlers>
-
JavaBean
public class DateBean { private Long id; private Date time1; private String time2; private Date time3; }
-
Mapper.xml
<?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.zm.Mapper.DateBeanMapper"> <select id="selectByID" resultType="com.zm.entity.DateBean" parameterType="long"> select id,time1,time2,time3 from datebean where id = #{id} </select> <insert id="InsertDate" parameterType="com.zm.entity.DateBean" > insert into datebean(time1,time2,time3) values ( #{time1,jdbcType=DATE}, #{time2}, #{time3,jdbcType=VARCHAR,typeHandler=com.zm.config.MyDateTypeHandler}) </insert> </mapper>
-
Insert操作
@Test public void test4(){ SqlSession session = sqlSessionFactory.openSession(); DateBeanMapper DateBeanMapper = session.getMapper(DateBeanMapper.class); DateBean dateBean = new DateBean(); dateBean.setTime1(new Date()); dateBean.setTime2("2019-12-13 21:44:43"); dateBean.setTime3(new Date()); DateBeanMapper.InsertDate(dateBean); session.commit(); session.close(); }
-
查询操作
@Test
public void test5(){
SqlSession session = sqlSessionFactory.openSession();
DateBeanMapper DateBeanMapper = session.getMapper(DateBeanMapper.class);
DateBean dateBean = DateBeanMapper.selectByID(2L);
System.out.println(dateBean);
}
-
测试结果说明
Insert情况:
- time1,time2,time3都不设置jdbcType和typeHandler。 可以插入成功
- time1,time2,time3都不设置jdbcType和typeHandler。 可以插入成功
2. time1,tiem2都不设置jdbcType和typeHandler,tiem3设置jdbcType和typeHandler。在MyDateTypeHandler类中打断点,Debug模式可以进入到方法中。
select情况:
在MyDateTypeHandler类中打断点,Debug模式可以进入到方法中。
从上述几种情况总结:如果设置了TypeHandler,mybatis会根据TypeHandler的设置进行转换。
如果没设置TypeHandler,mybatis会自动选择合适的TypeHandler进行转换。
mybatis提供了大量的TypeHandler(具体可运行如下方法查看)。因此一般情况下,不需要自定义开发TypeHandler(枚举类型除外)。
/**
* 查看mybatis默认的typeHandler
*/
@Test
public void test6() {
SqlSession session = sqlSessionFactory.openSession();
TypeHandlerRegistry typeHandlerRegistry = session.getConfiguration().getTypeHandlerRegistry();
Collection<TypeHandler<?>> handlers = typeHandlerRegistry.getTypeHandlers();
System.out.println(handlers.size());
for (TypeHandler<?> typeHandler : handlers) {
System.out.println(typeHandler.getClass().getName());
}
}