聊聊 Mybatis 的类型转换接口 TypeHandler
mybatis 能够实现 jdbc 类型和 java 类型之间的转换,具体来说有一个类型转换器的接口:
类型处理器接口 TypeHandler
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;
}
类型处理器 BaseTypeHandler
jdbc 类型转为 java 类型
BaseTypeHandler 实现了 TypeHandler 接口,实现了 setParameter() 办法:
@Override
public void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException {if (parameter == null) {if (jdbcType == null) {throw new TypeException("JDBC requires that the JdbcType must be specified for all nullable parameters.");
}
try {ps.setNull(i, jdbcType.TYPE_CODE);
} catch (SQLException e) {
throw new TypeException("Error setting null for parameter #" + i + "with JdbcType" + jdbcType + "."
+ "Try setting a different JdbcType for this parameter or a different jdbcTypeForNull configuration property."
+ "Cause:" + e, e);
}
} else {
try {setNonNullParameter(ps, i, parameter, jdbcType);
} catch (Exception e) {
throw new TypeException("Error setting non null for parameter #" + i + "with JdbcType" + jdbcType + "."
+ "Try setting a different JdbcType for this parameter or a different configuration property."
+ "Cause:" + e, e);
}
}
}
这个办法中就是设置 PreparedStatement 的参数,也是参数绑定,将 jdbcType 转为 Java 类型,setNonNullParameter 是形象办法,依据不同的参数类型有不同的类实现了这个办法,比方 LongTypeHandler 实现的 setNonNullParameter() 办法:
@Override
public void setNonNullParameter(PreparedStatement ps, int i, Long parameter, JdbcType jdbcType)
throws SQLException {ps.setLong(i, parameter);
}
java 类型转为 jdbc 类型
BaseTypeHandler 的 getResult() 办法:
@Override
public T getResult(CallableStatement cs, int columnIndex) throws SQLException {
try {return getNullableResult(cs, columnIndex);
} catch (Exception e) {throw new ResultMapException("Error attempting to get column #" + columnIndex + "from callable statement. Cause:" + e, e);
}
}
办法也比较简单,间接调用了 getNullableResult 抽象类,性能就是从 ResultSet 中获取数据,把 Java 类型转换为 JdbcType 类型,比方 LongTypeHandler 实现的 getNullableResult():
@Override
public Long getNullableResult(ResultSet rs, String columnName)
throws SQLException {long result = rs.getLong(columnName);
return result == 0 && rs.wasNull() ? null : result;}
通过源码剖析咱们晓得了 TypeHandler 接口的作用就是用来实现类型转换的,mybatis 在初始化的时候就获取 TypeHandler,而后创立 TypeHandler 实例注册到 TypeHandlerRegistry 中,由 TypeHandlerRegistry 来进行治理这些实例,下篇文章中咱们介绍一下 TypeHandlerRegistry 这个类
总结
这篇文章讲了 Mybatis 的类型转换接口 TypeHandler 和它的实现类 BaseTypeHandler,类型转换接口显然就是实现 jdbc 类型和 java 类型之间的转换,同时剖析了 BaseTypeHandler 的 setParameter() 办法和 getResult() 办法,getNullableResult 是抽象类,具体方法由其余实现类进行实现。