TypeHandler作用
mybatis在预处理语句(PreparedStatement)中设置一个参数时,或者从结果集(ResultSet)中取出一个值时,都会用到TypeHandler。
它的作用就是将java类型(javaType)转化为jdbc类型(jdbcType),或者将jdbc类型(jdbcType)转化为java类型(javaType)
内置TypeHandler
我们可以去自定义一个TypeHandler,然而大多数情况下并不需要这么做,因为Mybatis已经为我们内置了常用的TypeHandler,这些TypeHandler对我们常用的基本类型,如整形、字符串、日期等都作了相应的支持。
默认注册的TypeHandler如下:
register(Boolean.class, new BooleanTypeHandler());
register(boolean.class, new BooleanTypeHandler());
register(JdbcType.BOOLEAN, new BooleanTypeHandler());
register(JdbcType.BIT, new BooleanTypeHandler());
register(Byte.class, new ByteTypeHandler());
register(byte.class, new ByteTypeHandler());
register(JdbcType.TINYINT, new ByteTypeHandler());
register(Short.class, new ShortTypeHandler());
register(short.class, new ShortTypeHandler());
register(JdbcType.SMALLINT, new ShortTypeHandler());
register(Integer.class, new IntegerTypeHandler());
register(int.class, new IntegerTypeHandler());
register(JdbcType.INTEGER, new IntegerTypeHandler());
register(Long.class, new LongTypeHandler());
register(long.class, new LongTypeHandler());
register(Float.class, new FloatTypeHandler());
register(float.class, new FloatTypeHandler());
register(JdbcType.FLOAT, new FloatTypeHandler());
register(Double.class, new DoubleTypeHandler());
register(double.class, new DoubleTypeHandler());
register(JdbcType.DOUBLE, new DoubleTypeHandler());
register(Reader.class, new ClobReaderTypeHandler());
register(String.class, new StringTypeHandler());
register(String.class, JdbcType.CHAR, new StringTypeHandler());
register(String.class, JdbcType.CLOB, new ClobTypeHandler());
register(String.class, JdbcType.VARCHAR, new StringTypeHandler());
register(String.class, JdbcType.LONGVARCHAR, new ClobTypeHandler());
register(String.class, JdbcType.NVARCHAR, new NStringTypeHandler());
register(String.class, JdbcType.NCHAR, new NStringTypeHandler());
register(String.class, JdbcType.NCLOB, new NClobTypeHandler());
register(JdbcType.CHAR, new StringTypeHandler());
register(JdbcType.VARCHAR, new StringTypeHandler());
register(JdbcType.CLOB, new ClobTypeHandler());
register(JdbcType.LONGVARCHAR, new ClobTypeHandler());
register(JdbcType.NVARCHAR, new NStringTypeHandler());
register(JdbcType.NCHAR, new NStringTypeHandler());
register(JdbcType.NCLOB, new NClobTypeHandler());
register(Object.class, JdbcType.ARRAY, new ArrayTypeHandler());
register(JdbcType.ARRAY, new ArrayTypeHandler());
register(BigInteger.class, new BigIntegerTypeHandler());
register(JdbcType.BIGINT, new LongTypeHandler());
register(BigDecimal.class, new BigDecimalTypeHandler());
register(JdbcType.REAL, new BigDecimalTypeHandler());
register(JdbcType.DECIMAL, new BigDecimalTypeHandler());
register(JdbcType.NUMERIC, new BigDecimalTypeHandler());
register(InputStream.class, new BlobInputStreamTypeHandler());
register(Byte[].class, new ByteObjectArrayTypeHandler());
register(Byte[].class, JdbcType.BLOB, new BlobByteObjectArrayTypeHandler());
register(Byte[].class, JdbcType.LONGVARBINARY, new BlobByteObjectArrayTypeHandler());
register(byte[].class, new ByteArrayTypeHandler());
register(byte[].class, JdbcType.BLOB, new BlobTypeHandler());
register(byte[].class, JdbcType.LONGVARBINARY, new BlobTypeHandler());
register(JdbcType.LONGVARBINARY, new BlobTypeHandler());
register(JdbcType.BLOB, new BlobTypeHandler());
register(Object.class, UNKNOWN_TYPE_HANDLER);
register(Object.class, JdbcType.OTHER, UNKNOWN_TYPE_HANDLER);
register(JdbcType.OTHER, UNKNOWN_TYPE_HANDLER);
register(Date.class, new DateTypeHandler());
register(Date.class, JdbcType.DATE, new DateOnlyTypeHandler());
register(Date.class, JdbcType.TIME, new TimeOnlyTypeHandler());
register(JdbcType.TIMESTAMP, new DateTypeHandler());
register(JdbcType.DATE, new DateOnlyTypeHandler());
register(JdbcType.TIME, new TimeOnlyTypeHandler());
register(java.sql.Date.class, new SqlDateTypeHandler());
register(java.sql.Time.class, new SqlTimeTypeHandler());
register(java.sql.Timestamp.class, new SqlTimestampTypeHandler());
// mybatis-typehandlers-jsr310
if (Jdk.dateAndTimeApiExists) {
this.register(Instant.class, InstantTypeHandler.class);
this.register(LocalDateTime.class, LocalDateTimeTypeHandler.class);
this.register(LocalDate.class, LocalDateTypeHandler.class);
this.register(LocalTime.class, LocalTimeTypeHandler.class);
this.register(OffsetDateTime.class, OffsetDateTimeTypeHandler.class);
this.register(OffsetTime.class, OffsetTimeTypeHandler.class);
this.register(ZonedDateTime.class, ZonedDateTimeTypeHandler.class);
this.register(Month.class, MonthTypeHandler.class);
this.register(Year.class, YearTypeHandler.class);
this.register(YearMonth.class, YearMonthTypeHandler.class);
this.register(JapaneseDate.class, JapaneseDateTypeHandler.class);
}
// issue #273
register(Character.class, new CharacterTypeHandler());
register(char.class, new CharacterTypeHandler());
自定义枚举TypeHandler
然而枚举类型Mybatis对其只支持内置的name和ordinal属性,如果我们自己定义了一个枚举,定义了一个属性,这个属性是跟数据库字段值相关的,那么我们需要自定义一个枚举TypeHandler来实现。
实现步骤如下:
- 编写对应枚举类
- 编写枚举类对应的TypeHandler
- 在Mybatis配置文件中注册自定义的枚举TypeHandler
代码如下:
BlogType.java
package org.wbw.mybatisplus.type;
import java.util.HashMap;
import java.util.Map;
public enum BlogType {
Program(1),
Literature(2);
private int code;
BlogType(int code) {
this.code = code;
}
public int getCode() {
return this.code;
}
private static Map<Integer, BlogType> blogTypeMap = new HashMap<>();
static {
BlogType[] blogTypes = values();
for (BlogType blogType : blogTypes) {
blogTypeMap.put(blogType.code, blogType);
}
}
public static BlogType codeOf(int code) {
return blogTypeMap.get(code);
}
}
BlogTypeHandler.java
package org.wbw.mybatisplus.handler;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.wbw.mybatisplus.type.BlogType;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class BlogTypeHandler extends BaseTypeHandler<BlogType> {
@Override
public void setNonNullParameter(PreparedStatement ps, int i, BlogType parameter, JdbcType jdbcType) throws SQLException {
ps.setInt(i, parameter.getCode());
}
@Override
public BlogType getNullableResult(ResultSet rs, String columnName) throws SQLException {
int code = rs.getInt(columnName);
return BlogType.codeOf(code);
}
@Override
public BlogType getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
int code = rs.getInt(columnIndex);
return BlogType.codeOf(code);
}
@Override
public BlogType getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
return null;
}
}
mybatis-config.xml
<configuration>
<typeHandlers>
<typeHandler handler="org.wbw.mybatisplus.handler.BlogTypeHandler"
javaType="org.wbw.mybatisplus.type.BlogType"/>
</typeHandlers>