Statementhandler在执行增删改查操作时,使用ParameterHandler和ResultSetHandler来分别进行参数的设置和查寻结果的封装,其中在设置参数的时候是将传入参数设置到sql中,以及将从数据库查寻的结果转换成相应的java返回类型,都是通过TypeHandler来处理的。
public interface TypeHandler<T> {
void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException;
/**
* @param columnName Colunm name, when configuration <code>useColumnLabel</code> is <code>false</code>
*/
T getResult(ResultSet rs, String columnName) throws SQLException;
T getResult(ResultSet rs, int columnIndex) throws SQLException;
T getResult(CallableStatement cs, int columnIndex) throws SQLException;
}
TypeHandler是通过JDBC的技术来操作的,其各种实现类分别实现了不同参数的类型转换。
如FloatTypeHandler的源码:
public class FloatTypeHandler extends BaseTypeHandler<Float> {
@Override
public void setNonNullParameter(PreparedStatement ps, int i, Float parameter, JdbcType jdbcType)
throws SQLException {
ps.setFloat(i, parameter);
}
@Override
public Float getNullableResult(ResultSet rs, String columnName)
throws SQLException {
float result = rs.getFloat(columnName);
return result == 0 && rs.wasNull() ? null : result;
}
@Override
public Float getNullableResult(ResultSet rs, int columnIndex)
throws SQLException {
float result = rs.getFloat(columnIndex);
return result == 0 && rs.wasNull() ? null : result;
}
@Override
public Float getNullableResult(CallableStatement cs, int columnIndex)
throws SQLException {
float result = cs.getFloat(columnIndex);
return result == 0 && cs.wasNull() ? null : result;
}
}
默认情况下Mybatis会自动找到相匹配的typeHandler处理,如果对于特定的类型,如枚举,默认使用枚举名来存储到数据库,Mybatis还提供了存储枚举索引,如果需要使用特定的TypeHandler,则可以在全局配置中使用配置,handler表示需要使用的typeHandler,javaType则表示需要转换的java类型。
除了在全局配置文件中可以设置使用TypeHandler,也可以在处理某个字段的时候告诉Mybatis用什么类型处理器。在插入和更新的时候可以直接在字段后面写typeHandler
<insert id="insertStudent" parameterType="com.learncmzy.pojo.StudentBean" useGeneratedKeys="true" keyProperty="id">
insert into t_student(id,cnname,sex,note) values(#{id},#{cnname},#{sex,typeHandler=类型处理器全类名},#{note})
</insert>
在查询的时候可以指定自定义resultMap,在resultMap中指定相关字段使用具体的类型转换器
<result property="sex" column="sex" typeHandler="类型处理其全类名"/>
注意:如果在参数位置修改TypeHandler,应该保证保存数据和查寻数据用的TypeHandler是一样的。