当 MyBatis 将一个 Java 对象作为输入参数执行 INSERT 语句操作时,它会创建一个 PreparedStatement 对象,并且 使用 setXXX()方式对占位符设置相应的参数值,当从 SQL 结果集构 建 JavaBean 时,也有类似的过程。
MyBatis 对于以下的类型使用内建的类型处理器:所有的基本数据类型、基本类型的包装类型、byte[]、 java.util.Date、java.sql.Date、java,sql.Time、java.sql.Timestamp、Enum类型等。对于自定义类型,持久化和查询则可创建自定义typeHandlers类型处理器。
typeHandlers原理
对于如下mapper
<insert id="insertStudent" parameterType="Student">
INSERT INTO STUDENTS(STUD_ID,NAME,EMAIL,BIRTH)
VALUES(#{studId},#{name},#{email},#{birth})
</insert>
执行预处理
PreparedStatement pstmt = connection.prepareStatement
("INSERT INTO STUDENTS(STUD_ID,NAME,EMAIL,birth) VALUES(?,?,?,?)")
通过使用类型处理器typeHandlers设置参数,对于java.util.Date 类型转会换为 java.sql.Timestamp 设值(见:DateTypeHandler)。
pstmt.setInt(1,student.getStudId());
pstmt.setString(2, student.getName());
pstmt.setString(3, student.getEmail());
pstmt.setTimestamp(4, new Timestamp(student.getBirth().getTime()));
自定义typeHandlers
对于如下自定义枚举类型则需要新建typeHandlers
public enum ThirdPartyLogType {
ITEM(0, "商品"), TRADE(1, "订单"), SUPPLIER(2, "供应商");
private int type;
private String name;
ThirdPartyLogType(int type, String name) {
this.type = type;
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public static ThirdPartyLogType valuesOf(int type) {
for (ThirdPartyLogType thirdPartyLogType : ThirdPartyLogType.values()) {
if (thirdPartyLogType.getType() == type) {
return thirdPartyLogType;
}
}
return null;
}
}
ThirdPartyLogTypeTypeHandler如下:
@MappedTypes(ThirdPartyLogType.class)
public class ThirdPartyLogTypeTypeHandler extends EnumTypeHandler<ThirdPartyLogType> {
public ThirdPartyLogTypeTypeHandler(Class<ThirdPartyLogType> type) {
super(type);
}
@Override
public void setNonNullParameter(PreparedStatement ps, int i, ThirdPartyLogType parameter, JdbcType jdbcType) throws SQLException {
if (jdbcType == null) {
ps.setInt(i, parameter.getType());
} else {
ps.setObject(i, parameter.name(), jdbcType.TYPE_CODE);
}
}
@Override
public ThirdPartyLogType getNullableResult(ResultSet rs, String columnName) throws SQLException {
int s = rs.getInt(columnName);
return ThirdPartyLogType.valuesOf(s);
}
@Override
public ThirdPartyLogType getNullableResult(ResultSet rs, int columnIndex) throws SQLException{
int s = rs.getInt(columnIndex);
return ThirdPartyLogType.valuesOf(s);
}
@Override
public ThirdPartyLogType getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
int s = cs.getInt(columnIndex);
return ThirdPartyLogType.valuesOf(s);
}
}
注册typeHandlers
对于自定义typeHandlers需要注册,可以使用SqlSessionFactory中的typeHandlersPackage或typeHandlers进行注册
<bean id="sqlSessionFactory" class="org.mybatis.HgjSqlSessionFactoryBean">
<property name="mapperLocations" value="classpath*:org/dinozhang/**/dao/xml/**/*.xml"></property>
<property name="dataSource" ref="dataSource" />
<property name="typeHandlersPackage" value="org.dinozhang.typehandler"/>
</bean>