Mybatis之类型处理器
无论是MyBatis在预处理语句(PreparedStatement)中设置一个参数时,还是从结果集中取出一个值时, 都会用类型处理器将获取的值以合适的方式转换成 Java 类型,下表描述了一些默认的类型处理器.
类型处理器 | 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 |
你可以重写类型处理器或创建你自己的类型处理器来处理不支持的或非标准的类型,具体做法为:实现 org.apache.ibatis.type.TypeHandler 接口,或继承一个很便利的类 org.apache.ibatis.type.BaseTypeHandler我们就举一个简单的例子,我们先看个实体类.
public class Student {
private int id;
private String name;
private boolean pass;//注意他的类型是布尔。我们要把他转成int放到数据库
//get 和 set 省略
}
第一步:实现TypeHandler
package com.jiepi.util;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;
import org.apache.ibatis.type.TypeHandler;
import java.sql.*;
public class MyTypeHandler implements TypeHandler {
//在设置参数的时候调用
public void setParameter(PreparedStatement preparedStatement, int i, Object param, JdbcType jdbcType) throws SQLException {
if (param == null) {
preparedStatement.setInt(i,0);
return;
}
Boolean pass = (Boolean) param;
int value = pass ? 1 : 0;
preparedStatement.setInt(i,value);
}
//从数据库获取数据调用
public Object getResult(ResultSet resultSet, String s) throws SQLException {
int value = resultSet.getInt(s);
if (value == 1) {
return Boolean.TRUE;
}
return Boolean.FALSE;
}
public Object getResult(ResultSet resultSet, int i) throws SQLException {
int value = resultSet.getInt(i);
if (value == 1) {
return Boolean.TRUE;
}
return Boolean.FALSE;
}
public Object getResult(CallableStatement callableStatement, int i) throws SQLException {
int value = callableStatement.getInt(i);
if (value == 1) {
return Boolean.TRUE;
}
return Boolean.FALSE;
}
}
第二步:在mybatis配置注册TypeHandler(myBatis-config.xml).
<typeHandlers>
<typeHandler handler="com.jiepi.util.MyTypeHandler" jdbcType="NUMERIC" javaType="java.lang.Boolean"/>
</typeHandlers>
第三步:在映射文件中设置使用TypeHandler.
注意:使用上述的类型处理器将会覆盖已经存在的处理 Java 的 Boolean 类型属性和 NUMERIC 参数及结果的类型处理器。要注意 MyBatis 不会通过窥探数据库元信息来决定使用哪种类型,所以你必须在参数和结果映射中指明那是 NUMERIC 类型的字段, 以使其能够绑定到正确的类型处理器上。这是因为 MyBatis 直到语句被执行时才清楚数据类型.
<resultMap id="studentMap" type="com.jiepi.beans.Student">
<id property="id" column="id"/>
<result property="name" column="name"/>
<result property="pass" column="pass" typeHandler="com.jiepi.util.MyTypeHandler" jdbcType="NUMERIC" javaType="java.lang.Boolean"/>
</resultMap>
<insert id="add">//typeHandler 是没有双引号的
INSERT INTO Student (id, name, pass) VALUES (#{id}, #{name}, #{pass,jdbcType=NUMERIC,javaType=java.lang.Boolean,typeHandler=com.jiepi.util.MyTypeHandler})
</insert>
<select id="find" resultMap="studentMap">
SELECT * FROM Student
</select>
第四步:测试结果.
@Test
public void find() {
StudentMapper dao = session.getMapper(StudentMapper.class);
List<Student> student = dao.find();
student.stream().map(it->it.toString()).forEach(System.out::println);
System.out.println(student);
}
@Test
public void add1() {
StudentMapper dao = session.getMapper(StudentMapper.class);
Student student = new Student();
student.setName("jiepi");
student.setPass(true);//这里是boolean
dao.add(student);
session.commit();
}
运行结果:
[DEBUG] Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@15a34df2]
[DEBUG] ==> Preparing: INSERT INTO Student (id, name, pass) VALUES (?, ?, ?)
int int
[DEBUG] ==> Parameters: 0(Integer), jiepi(String), 1(Integer)//这里变成了1
[DEBUG] <== Updates: 1
[DEBUG] Committing JDBC Connection [com.mysql.jdbc.JDBC4Connection@15a34df2]
Disconnected from the target VM, address: '127.0.0.1:51494', transport: 'socket'
1.当然也还可以使用注解分别是MappedJdbcTypes和MappedTypes代替映射文件里面的jdbcType 和javeType.
2.mybatis配置文件上面的配置只能一个个的去配置类型处理,因此我们还可以自动查找查找类型处理器.
<typeHandlers>
<package name="com.jiepi.util"/>
</typeHandlers>