2 Mybatis基础支持层
2.1 类型转换模块
JDBC的数据类型与Java的数据类型并不是完全对应的,在PreparedStatement
为SQL绑定参数时,需要从Java类型转换成JDBC类型,当查询出结果时,又需要将JDBC类型转成Java类型。
该模块的功能作用非常明确,也很容易理解,此处只是学习源码怎么设计,怎么优雅的去实现这个功能。
2.1.1 JdbcType枚举类
首先,JDBC的所有数据类型都记录在java.sql.Types
类中,每一种类型都用final static int
表示。
public class Types {
public final static int BIT = -7;
public final static int TINYINT = -6;
public final static int SMALLINT = 5;
在Mybatis中,使用了一个JdbcType
枚举类去代表java.sql.Types
,其实就是包装了一下sql中的Types类而已。
public enum JdbcType {
//就是包装一下java.sql.Types
ARRAY(Types.ARRAY),
BIT(Types.BIT),
TINYINT(Types.TINYINT),
SMALLINT(Types.SMALLINT),
......
}
JdbcType
类中还定义了一个静态Map集合维护常量编码与JdbcType之间的对应关系
public final int TYPE_CODE;
private static Map<Integer,JdbcType> codeLookup = new HashMap<Integer,JdbcType>();
//一开始就将数字对应的枚举型放入hashmap
static {
for (JdbcType type : JdbcType.values()) {
codeLookup.put(type.TYPE_CODE, type);
}
}
2.1.2 TypeHandler
TypeHandler
为类型转换器的接口,定义了JdbcType与Java数据类型之间互转的方法。
为了方便用户自定义TypeHandler,Mybatis提供了BaseTypeHandler
这个抽象类,只需要重写setNonNullParameter
方法和getNullableResult
方法。
setNonNullParameter
:主要负责将Java类型的参数转换成JdbcType类型,并绑定到SQL。getNullableResult
:将JdbcType类型的数据转成Java类型并封装成Java对象。
BaseTypeHandler
有许多实现子类,每个子类负责一个类型的转换。
以IntegerTypeHandler为例,看一下源码实现:
public class IntegerTypeHandler extends BaseTypeHandler<Integer> {
@Override
public void setNonNullParameter(PreparedStatement ps, int i, Integer parameter, JdbcType jdbcType)
throws SQLException {
ps.setInt(i, parameter);
}
@Override
public Integer getNullableResult(ResultSet rs, String columnName)
throws SQLException {
return rs.getInt(columnName);
}
@Override
public Integer getNullableResult(ResultSet rs, int columnIndex)
throws SQLException {
return rs.getInt(columnIndex);
}
@Override
public Integer getNullableResult(CallableStatement cs, int columnIndex)
throws SQLException {
return cs.getInt(columnIndex);
}
}
基本上依赖于JDBC实现即可。
2.1.3 TypeHandlerRegistry
我们已经知道,要将JdbcType与Java Type之间的转换只需要使用对应的TypeHandler实现类即可,但是如何知道该使用哪个实现类呢?这个功能就是由TypeHandlerRegistry
完成。