代码拉取完成,页面将自动刷新
同步操作将从 flatfish/Java-Review 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
对应 type
包
如下所示
MyBatis 为简化配置文件提供了别名机制,该机制是类型转换模块的主要功能之一
类型转换模块的另一个功能是实现 JDBC 类型与 Java 类型之间的转换,该功能在为 SQL 语句绑定实参以及映射查询结果集时都会涉及:
本篇主要讲解的类
org.apache.ibatis.type.TypeHandler
,类型转换处理器public interface TypeHandler<T> {
// 设置 PreparedStatement 的指定参数
// ps:PreparedStatement 对象
// i:参数占位符的位置
// parameter:参数
// jdbcType:JDBC类型
// SQLException 异常
void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException;
// 获得 ResultSet的指定字段
// rs:ResultSet 对象
// columnName:字段名
// 返回结果
T getResult(ResultSet rs, String columnName) throws SQLException;
// 获得位置指定的值
// rs:结果集
// columnIndex:字段位置
T getResult(ResultSet rs, int columnIndex) throws SQLException;
// 获得 CallableStatement 的指定字段的值
T getResult(CallableStatement cs, int columnIndex) throws SQLException;
}
org.apache.ibatis.type.BaseTypeHandler
,实现 TypeHandler 接口,继承 TypeReference 抽象类,TypeHandler 基础抽象类public abstract class BaseTypeHandler<T> extends TypeReference<T> implements TypeHandler<T> {
@Deprecated
protected Configuration configuration;
@Deprecated
public void setConfiguration(Configuration c) {
this.configuration = c;
}
@Override
public void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException {
// 参数为空的时候,设置为null
if (parameter == null) {
if (jdbcType == null) {
throw new TypeException("JDBC requires that the JdbcType must be specified for all nullable parameters.");
}
try {
// 设置为null
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);
}
}
}
@Override
public T getResult(ResultSet rs, String columnName) throws SQLException {
try {
return getNullableResult(rs, columnName);
} catch (Exception e) {
throw new ResultMapException("Error attempting to get column '" + columnName + "' from result set. Cause: " + e, e);
}
}
@Override
public T getResult(ResultSet rs, int columnIndex) throws SQLException {
try {
return getNullableResult(rs, columnIndex);
} catch (Exception e) {
throw new ResultMapException("Error attempting to get column #" + columnIndex + " from result set. Cause: " + e, e);
}
}
@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);
}
}
// 以下方法由子类实现
public abstract void setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException;
public abstract T getNullableResult(ResultSet rs, String columnName) throws SQLException;
public abstract T getNullableResult(ResultSet rs, int columnIndex) throws SQLException;
public abstract T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException;
}
org.apache.ibatis.type.IntegerTypeHandler
,继承 BaseTypeHandler 抽象类,Integer 类型的 TypeHandler 实现类。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 {
// 获得字段的值
int result = rs.getInt(columnName);
// 先通过 rs 判断是否空。如果是空就返回null 否则返回 result
return result == 0 && rs.wasNull() ? null : result;
}
@Override
public Integer getNullableResult(ResultSet rs, int columnIndex)
throws SQLException {
// 获得字段的值
int result = rs.getInt(columnIndex);
// 先通过 rs 判断是否空。如果是空就返回null 否则返回 result
return result == 0 && rs.wasNull() ? null : result;
}
@Override
public Integer getNullableResult(CallableStatement cs, int columnIndex)
throws SQLException {
// 获得字段的值
int result = cs.getInt(columnIndex);
// 先通过 rs 判断是否空。如果是空就返回null 否则返回 result
return result == 0 && cs.wasNull() ? null : result;
}
}
org.apache.ibatis.type.DateTypeHandler
,继承 BaseTypeHandler 抽象类,Date 类型的 TypeHandler 实现类。public class DateTypeHandler extends BaseTypeHandler<Date> {
@Override
public void setNonNullParameter(PreparedStatement ps, int i, Date parameter, JdbcType jdbcType)
throws SQLException {
// 将 Date 转换成 Timestamp 类型
// 然后设置到 ps 中
ps.setTimestamp(i, new Timestamp(parameter.getTime()));
}
@Override
public Date getNullableResult(ResultSet rs, String columnName)
throws SQLException {
// 获得 Timestamp 的值
Timestamp sqlTimestamp = rs.getTimestamp(columnName);
if (sqlTimestamp != null) {
// 将 Timestamp 转换成 Date Timestamp 类型
return new Date(sqlTimestamp.getTime());
}
return null;
}
@Override
public Date getNullableResult(ResultSet rs, int columnIndex)
throws SQLException {
Timestamp sqlTimestamp = rs.getTimestamp(columnIndex);
if (sqlTimestamp != null) {
return new Date(sqlTimestamp.getTime());
}
return null;
}
@Override
public Date getNullableResult(CallableStatement cs, int columnIndex)
throws SQLException {
Timestamp sqlTimestamp = cs.getTimestamp(columnIndex);
if (sqlTimestamp != null) {
return new Date(sqlTimestamp.getTime());
}
return null;
}
}
org.apache.ibatis.type.DateOnlyTypeHandler
,继承 BaseTypeHandler 抽象类,Date 类型的 TypeHandler 实现类public class DateOnlyTypeHandler extends BaseTypeHandler<Date> {
@Override
public void setNonNullParameter(PreparedStatement ps, int i, Date parameter, JdbcType jdbcType)
throws SQLException {
// 将 java Date 转换成 sql Date 类型
ps.setDate(i, new java.sql.Date(parameter.getTime()));
}
@Override
public Date getNullableResult(ResultSet rs, String columnName)
throws SQLException {
// 获得 SQL Date的值
java.sql.Date sqlDate = rs.getDate(columnName);
if (sqlDate != null) {
// 将 SQL Date 转换成 Java Date类型
return new Date(sqlDate.getTime());
}
return null;
}
// 下面的方法很简单
@Override
public Date getNullableResult(ResultSet rs, int columnIndex)
throws SQLException {
java.sql.Date sqlDate = rs.getDate(columnIndex);
if (sqlDate != null) {
return new Date(sqlDate.getTime());
}
return null;
}
@Override
public Date getNullableResult(CallableStatement cs, int columnIndex)
throws SQLException {
java.sql.Date sqlDate = cs.getDate(columnIndex);
if (sqlDate != null) {
return new Date(sqlDate.getTime());
}
return null;
}
}
org.apache.ibatis.type.EnumTypeHandler
,继承 BaseTypeHandler 抽象类,Enum 类型的 TypeHandler 实现类。public class EnumTypeHandler<E extends Enum<E>> extends BaseTypeHandler<E> {
// 枚举类型
private final Class<E> type;
public EnumTypeHandler(Class<E> type) {
if (type == null) {
throw new IllegalArgumentException("Type argument cannot be null");
}
this.type = type;
}
@Override
public void setNonNullParameter(PreparedStatement ps, int i, E parameter, JdbcType jdbcType) throws SQLException {
// 将枚举转换为 String 类型
if (jdbcType == null) {
ps.setString(i, parameter.name());
} else {
ps.setObject(i, parameter.name(), jdbcType.TYPE_CODE); // see r3589
}
}
@Override
public E getNullableResult(ResultSet rs, String columnName) throws SQLException {
// 获得 String 的值
String s = rs.getString(columnName);
// 将String转换为Enum类型
return s == null ? null : Enum.valueOf(type, s);
}
@Override
public E getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
// 获得 String 的值
String s = rs.getString(columnName);
// 将String转换为Enum类型
return s == null ? null : Enum.valueOf(type, s);
}
@Override
public E getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
String s = cs.getString(columnIndex);
return s == null ? null : Enum.valueOf(type, s);
}
}
org.apache.ibatis.type.EnumOrdinalTypeHandler
,继承 BaseTypeHandler 抽象类,Enum 类型的 TypeHandler 实现类public class EnumOrdinalTypeHandler<E extends Enum<E>> extends BaseTypeHandler<E> {
// 枚举类
private final Class<E> type;
// type下的所有的枚举类
private final E[] enums;
public EnumOrdinalTypeHandler(Class<E> type) {
if (type == null) {
throw new IllegalArgumentException("Type argument cannot be null");
}
this.type = type;
this.enums = type.getEnumConstants();
if (this.enums == null) {
throw new IllegalArgumentException(type.getSimpleName() + " does not represent an enum type.");
}
}
@Override
public void setNonNullParameter(PreparedStatement ps, int i, E parameter, JdbcType jdbcType) throws SQLException {
// 将Enum转换为 int 类型
ps.setInt(i, parameter.ordinal());
}
// 下面的方法类似,比较简单不再赘述
@Override
public E getNullableResult(ResultSet rs, String columnName) throws SQLException {
int ordinal = rs.getInt(columnName);
if (ordinal == 0 && rs.wasNull()) {
return null;
}
return toOrdinalEnum(ordinal);
}
@Override
public E getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
int ordinal = rs.getInt(columnIndex);
if (ordinal == 0 && rs.wasNull()) {
return null;
}
return toOrdinalEnum(ordinal);
}
@Override
public E getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
int ordinal = cs.getInt(columnIndex);
if (ordinal == 0 && cs.wasNull()) {
return null;
}
return toOrdinalEnum(ordinal);
}
private E toOrdinalEnum(int ordinal) {
try {
return enums[ordinal];
} catch (Exception ex) {
throw new IllegalArgumentException("Cannot convert " + ordinal + " to " + type.getSimpleName() + " by ordinal value.", ex);
}
}
}
org.apache.ibatis.type.ObjectTypeHandler
,继承 BaseTypeHandler 抽象类,Object 类型的 TypeHandler 实现类public class ObjectTypeHandler extends BaseTypeHandler<Object> {
@Override
public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType)
throws SQLException {
ps.setObject(i, parameter);
}
@Override
public Object getNullableResult(ResultSet rs, String columnName)
throws SQLException {
return rs.getObject(columnName);
}
@Override
public Object getNullableResult(ResultSet rs, int columnIndex)
throws SQLException {
return rs.getObject(columnIndex);
}
@Override
public Object getNullableResult(CallableStatement cs, int columnIndex)
throws SQLException {
return cs.getObject(columnIndex);
}
}
org.apache.ibatis.type.UnknownTypeHandler
,继承 BaseTypeHandler 抽象类,未知的 TypeHandler 实现类。通过获取对应的 TypeHandler ,进行处理public class UnknownTypeHandler extends BaseTypeHandler<Object> {
// 单例
private static final ObjectTypeHandler OBJECT_TYPE_HANDLER = new ObjectTypeHandler();
// TODO Rename to 'configuration' after removing the 'configuration' property(deprecated property) on parent class
// 配置
private final Configuration config;
// 注册表
private final Supplier<TypeHandlerRegistry> typeHandlerRegistrySupplier;
/**
* The constructor that pass a MyBatis configuration.
*
* @param configuration a MyBatis configuration
* @since 3.5.4
*/
public UnknownTypeHandler(Configuration configuration) {
this.config = configuration;
this.typeHandlerRegistrySupplier = configuration::getTypeHandlerRegistry;
}
/**
* The constructor that pass the type handler registry.
*
* @param typeHandlerRegistry a type handler registry
* @deprecated Since 3.5.4, please use the {@link #UnknownTypeHandler(Configuration)}.
*/
@Deprecated
public UnknownTypeHandler(TypeHandlerRegistry typeHandlerRegistry) {
this.config = new Configuration();
this.typeHandlerRegistrySupplier = () -> typeHandlerRegistry;
}
@Override
public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType)
throws SQLException {
// 获得参数对应的处理器
TypeHandler handler = resolveTypeHandler(parameter, jdbcType);
// 使用 handler 设置参数
handler.setParameter(ps, i, parameter, jdbcType);
}
@Override
public Object getNullableResult(ResultSet rs, String columnName)
throws SQLException {
// 获取参数对应的处理器
TypeHandler<?> handler = resolveTypeHandler(rs, columnName);
// 使用 handler
return handler.getResult(rs, columnName);
}
@Override
public Object getNullableResult(ResultSet rs, int columnIndex)
throws SQLException {
TypeHandler<?> handler = resolveTypeHandler(rs.getMetaData(), columnIndex);
// 获取不到,使用 OBJECT_TYPE_HANDLER
if (handler == null || handler instanceof UnknownTypeHandler) {
handler = OBJECT_TYPE_HANDLER;
}
return handler.getResult(rs, columnIndex);
}
@Override
public Object getNullableResult(CallableStatement cs, int columnIndex)
throws SQLException {
return cs.getObject(columnIndex);
}
private TypeHandler<?> resolveTypeHandler(Object parameter, JdbcType jdbcType) {
TypeHandler<?> handler;
if (parameter == null) {
handler = OBJECT_TYPE_HANDLER;
} else {
handler = typeHandlerRegistrySupplier.get().getTypeHandler(parameter.getClass(), jdbcType);
// check if handler is null (issue #270)
if (handler == null || handler instanceof UnknownTypeHandler) {
handler = OBJECT_TYPE_HANDLER;
}
}
return handler;
}
private TypeHandler<?> resolveTypeHandler(ResultSet rs, String column) {
try {
Map<String,Integer> columnIndexLookup;
columnIndexLookup = new HashMap<>();
ResultSetMetaData rsmd = rs.getMetaData();
int count = rsmd.getColumnCount();
boolean useColumnLabel = config.isUseColumnLabel();
for (int i = 1; i <= count; i++) {
String name = useColumnLabel ? rsmd.getColumnLabel(i) : rsmd.getColumnName(i);
columnIndexLookup.put(name,i);
}
Integer columnIndex = columnIndexLookup.get(column);
TypeHandler<?> handler = null;
if (columnIndex != null) {
handler = resolveTypeHandler(rsmd, columnIndex);
}
if (handler == null || handler instanceof UnknownTypeHandler) {
handler = OBJECT_TYPE_HANDLER;
}
return handler;
} catch (SQLException e) {
throw new TypeException("Error determining JDBC type for column " + column + ". Cause: " + e, e);
}
}
private TypeHandler<?> resolveTypeHandler(ResultSetMetaData rsmd, Integer columnIndex) {
TypeHandler<?> handler = null;
JdbcType jdbcType = safeGetJdbcTypeForColumn(rsmd, columnIndex);
Class<?> javaType = safeGetClassForColumn(rsmd, columnIndex);
if (javaType != null && jdbcType != null) {
handler = typeHandlerRegistrySupplier.get().getTypeHandler(javaType, jdbcType);
} else if (javaType != null) {
handler = typeHandlerRegistrySupplier.get().getTypeHandler(javaType);
} else if (jdbcType != null) {
handler = typeHandlerRegistrySupplier.get().getTypeHandler(jdbcType);
}
return handler;
}
private JdbcType safeGetJdbcTypeForColumn(ResultSetMetaData rsmd, Integer columnIndex) {
try {
return JdbcType.forCode(rsmd.getColumnType(columnIndex));
} catch (Exception e) {
return null;
}
}
private Class<?> safeGetClassForColumn(ResultSetMetaData rsmd, Integer columnIndex) {
try {
return Resources.classForName(rsmd.getColumnClassName(columnIndex));
} catch (Exception e) {
return null;
}
}
}
org.apache.ibatis.type.TypeReference
,引用泛型抽象类。目的很简单,就是解析类上定义的泛型public abstract class TypeReference<T> {
// 泛型
private final Type rawType;
protected TypeReference() {
rawType = getSuperclassTypeParameter(getClass());
}
Type getSuperclassTypeParameter(Class<?> clazz) {
// 从父类中获取泛型
Type genericSuperclass = clazz.getGenericSuperclass();
// 满足条件
if (genericSuperclass instanceof Class) {
// try to climb up the hierarchy until meet something useful
if (TypeReference.class != genericSuperclass) {
return getSuperclassTypeParameter(clazz.getSuperclass());
}
throw new TypeException("'" + getClass() + "' extends TypeReference but misses the type parameter. "
+ "Remove the extension or add a type parameter to it.");
}
// 获取泛型
Type rawType = ((ParameterizedType) genericSuperclass).getActualTypeArguments()[0];
// TODO remove this when Reflector is fixed to return Types
// 必须是泛型才能拿到
if (rawType instanceof ParameterizedType) {
rawType = ((ParameterizedType) rawType).getRawType();
}
return rawType;
}
public final Type getRawType() {
return rawType;
}
@Override
public String toString() {
return rawType.toString();
}
}
org.apache.ibatis.type.@MappedTypes
,匹配的 Java Type 类型的注解。@Documented
@Retention(RetentionPolicy.RUNTIME)
// 注册到类
@Target(ElementType.TYPE)
public @interface MappedTypes {
/**
* Returns java types to map {@link TypeHandler}.
*
* @return java types
*/
Class<?>[] value();
}
org.apache.ibatis.type.@MappedJdbcTypes
,匹配的 JDBC Type 类型的注解@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MappedJdbcTypes {
/**
* Returns jdbc types to map {@link TypeHandler}.
* 匹配 JDBC类型
* @return jdbc types
*/
JdbcType[] value();
/**
* Returns whether map to jdbc null type.
*
* @return {@code true} if map, {@code false} if otherwise
*/
boolean includeNullJdbcType() default false;
}
org.apache.ibatis.type.@Alias
,别名的注解。@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Alias {
/**
* Return the alias name.
*
* @return the alias name 别名
*/
String value();
}
org.apache.ibatis.type.JdbcType
,Jdbc Type 枚举。public enum JdbcType {
/*
* This is added to enable basic support for the
* ARRAY data type - but a custom type handler is still required
*/
ARRAY(Types.ARRAY),
BIT(Types.BIT),
TINYINT(Types.TINYINT),
SMALLINT(Types.SMALLINT),
INTEGER(Types.INTEGER),
BIGINT(Types.BIGINT),
FLOAT(Types.FLOAT),
REAL(Types.REAL),
DOUBLE(Types.DOUBLE),
NUMERIC(Types.NUMERIC),
DECIMAL(Types.DECIMAL),
CHAR(Types.CHAR),
VARCHAR(Types.VARCHAR),
LONGVARCHAR(Types.LONGVARCHAR),
DATE(Types.DATE),
TIME(Types.TIME),
TIMESTAMP(Types.TIMESTAMP),
BINARY(Types.BINARY),
VARBINARY(Types.VARBINARY),
LONGVARBINARY(Types.LONGVARBINARY),
NULL(Types.NULL),
OTHER(Types.OTHER),
BLOB(Types.BLOB),
CLOB(Types.CLOB),
BOOLEAN(Types.BOOLEAN),
CURSOR(-10), // Oracle
UNDEFINED(Integer.MIN_VALUE + 1000),
NVARCHAR(Types.NVARCHAR), // JDK6
NCHAR(Types.NCHAR), // JDK6
NCLOB(Types.NCLOB), // JDK6
STRUCT(Types.STRUCT),
JAVA_OBJECT(Types.JAVA_OBJECT),
DISTINCT(Types.DISTINCT),
REF(Types.REF),
DATALINK(Types.DATALINK),
ROWID(Types.ROWID), // JDK6
LONGNVARCHAR(Types.LONGNVARCHAR), // JDK6
SQLXML(Types.SQLXML), // JDK6
DATETIMEOFFSET(-155), // SQL Server 2008
TIME_WITH_TIMEZONE(Types.TIME_WITH_TIMEZONE), // JDBC 4.2 JDK8
TIMESTAMP_WITH_TIMEZONE(Types.TIMESTAMP_WITH_TIMEZONE); // JDBC 4.2 JDK8
// 类型编号
public final int TYPE_CODE;
private static Map<Integer,JdbcType> codeLookup = new HashMap<>();
static {
for (JdbcType type : JdbcType.values()) {
codeLookup.put(type.TYPE_CODE, type);
}
}
JdbcType(int code) {
this.TYPE_CODE = code;
}
public static JdbcType forCode(int code) {
return codeLookup.get(code);
}
}
org.apache.ibatis.type.TypeHandlerRegistry
,TypeHandler 注册表,相当于管理 TypeHandler 的容器,从其中能获取到对应的 TypeHandler// TypeHandlerRegistry.java
/**
* 空 TypeHandler 集合的标识,即使 {@link #TYPE_HANDLER_MAP} 中,某个 KEY1 对应的 Map<JdbcType, TypeHandler<?>> 为空。
*
* @see #getJdbcHandlerMap(Type)
*/
private static final Map<JdbcType, TypeHandler<?>> NULL_TYPE_HANDLER_MAP = Collections.emptyMap();
/**
* JDBC Type 和 {@link TypeHandler} 的映射
*
* {@link #register(JdbcType, TypeHandler)}
*/
private final Map<JdbcType, TypeHandler<?>> JDBC_TYPE_HANDLER_MAP = new EnumMap<>(JdbcType.class);
/**
* {@link TypeHandler} 的映射
*
* KEY1:JDBC Type
* KEY2:Java Type
* VALUE:{@link TypeHandler} 对象
*/
private final Map<Type, Map<JdbcType, TypeHandler<?>>> TYPE_HANDLER_MAP = new ConcurrentHashMap<>();
/**
* 所有 TypeHandler 的“集合”
*
* KEY:{@link TypeHandler#getClass()}
* VALUE:{@link TypeHandler} 对象
*/
private final Map<Class<?>, TypeHandler<?>> ALL_TYPE_HANDLERS_MAP = new HashMap<>();
/**
* {@link UnknownTypeHandler} 对象
*/
private final TypeHandler<Object> UNKNOWN_TYPE_HANDLER = new UnknownTypeHandler(this);
/**
* 默认的枚举类型的 TypeHandler 对象
*/
private Class<? extends TypeHandler> defaultEnumTypeHandler = EnumTypeHandler.class;
public TypeHandlerRegistry() {
// ... 省略其它类型的注册
// <1>
register(Date.class, new DateTypeHandler());
register(Date.class, JdbcType.DATE, new DateOnlyTypeHandler());
register(Date.class, JdbcType.TIME, new TimeOnlyTypeHandler());
// <2>
register(JdbcType.TIMESTAMP, new DateTypeHandler());
register(JdbcType.DATE, new DateOnlyTypeHandler());
register(JdbcType.TIME, new TimeOnlyTypeHandler());
// ... 省略其它类型的注册
}
// TypeHandlerRegistry.java
public <T> TypeHandler<T> getInstance(Class<?> javaTypeClass, Class<?> typeHandlerClass) {
// 获得 Class 类型的构造方法
if (javaTypeClass != null) {
try {
Constructor<?> c = typeHandlerClass.getConstructor(Class.class);
return (TypeHandler<T>) c.newInstance(javaTypeClass); // 符合这个条件的,例如 EnumTypeHandler
} catch (NoSuchMethodException ignored) {
// ignored 忽略该异常,继续向下
} catch (Exception e) {
throw new TypeException("Failed invoking constructor for handler " + typeHandlerClass, e);
}
}
// <2> 获得空参的构造方法
try {
Constructor<?> c = typeHandlerClass.getConstructor();
return (TypeHandler<T>) c.newInstance(); // 符合这个条件的,例如 IntegerTypeHandler
} catch (Exception e) {
throw new TypeException("Unable to find a usable constructor for " + typeHandlerClass, e);
}
}
private void register(Type javaType, JdbcType jdbcType, TypeHandler<?> handler) {
// <1> 添加 handler 到 TYPE_HANDLER_MAP 中
if (javaType != null) {
// 获得 Java Type 对应的 map
Map<JdbcType, TypeHandler<?>> map = TYPE_HANDLER_MAP.get(javaType);
if (map == null || map == NULL_TYPE_HANDLER_MAP) { // 如果不存在,则进行创建
map = new HashMap<>();
TYPE_HANDLER_MAP.put(javaType, map);
}
// 添加到 handler 中 map 中
map.put(jdbcType, handler);
}
// <2> 添加 handler 到 ALL_TYPE_HANDLERS_MAP 中
ALL_TYPE_HANDLERS_MAP.put(handler.getClass(), handler);
}
public void register(String packageName) {
// 扫描指定包下的所有 TypeHandler 类
ResolverUtil<Class<?>> resolverUtil = new ResolverUtil<>();
resolverUtil.find(new ResolverUtil.IsA(TypeHandler.class), packageName);
Set<Class<? extends Class<?>>> handlerSet = resolverUtil.getClasses();
// 遍历 TypeHandler 数组,发起注册
for (Class<?> type : handlerSet) {
//Ignore inner classes and interfaces (including package-info.java) and abstract classes
// 排除匿名类、接口、抽象类
if (!type.isAnonymousClass() && !type.isInterface() && !Modifier.isAbstract(type.getModifiers())) {
register(type);
}
}
}
// TypeHandlerRegistry.java
public void register(Class<?> typeHandlerClass) {
boolean mappedTypeFound = false;
// <3> 获得 @MappedTypes 注解
MappedTypes mappedTypes = typeHandlerClass.getAnnotation(MappedTypes.class);
if (mappedTypes != null) {
// 遍历注解的 Java Type 数组,逐个进行注册
for (Class<?> javaTypeClass : mappedTypes.value()) {
register(javaTypeClass, typeHandlerClass);
mappedTypeFound = true;
}
}
// <4> 未使用 @MappedTypes 注解,则直接注册
if (!mappedTypeFound) {
register(getInstance(null, typeHandlerClass)); // 创建 TypeHandler 对象
}
}
public void register(Class<?> javaTypeClass, Class<?> typeHandlerClass) {
register(javaTypeClass, getInstance(javaTypeClass, typeHandlerClass)); // 创建 TypeHandler 对象
}
// TypeHandlerRegistry.java
private <T> void register(Type javaType, TypeHandler<? extends T> typeHandler) {
// 获得 MappedJdbcTypes 注解
MappedJdbcTypes mappedJdbcTypes = typeHandler.getClass().getAnnotation(MappedJdbcTypes.class);
if (mappedJdbcTypes != null) {
// 遍历 MappedJdbcTypes 注册的 JDBC Type 进行注册
for (JdbcType handledJdbcType : mappedJdbcTypes.value()) {
register(javaType, handledJdbcType, typeHandler);
}
if (mappedJdbcTypes.includeNullJdbcType()) {
// <5>
register(javaType, null, typeHandler); // jdbcType = null
}
} else {
// <5>
register(javaType, null, typeHandler); // jdbcType = null
}
}
// TypeHandlerRegistry.java
public <T> void register(TypeHandler<T> typeHandler) {
boolean mappedTypeFound = false;
// <5> 获得 @MappedTypes 注解
MappedTypes mappedTypes = typeHandler.getClass().getAnnotation(MappedTypes.class);
// 优先,使用 @MappedTypes 注解的 Java Type 进行注册
if (mappedTypes != null) {
for (Class<?> handledType : mappedTypes.value()) {
register(handledType, typeHandler);
mappedTypeFound = true;
}
}
// @since 3.1.0 - try to auto-discover the mapped type
// <6> 其次,当 typeHandler 为 TypeReference 子类时,进行注册
if (!mappedTypeFound && typeHandler instanceof TypeReference) {
try {
TypeReference<T> typeReference = (TypeReference<T>) typeHandler;
register(typeReference.getRawType(), typeHandler); // Java Type 为 <T> 泛型
mappedTypeFound = true;
} catch (Throwable t) {
// maybe users define the TypeReference with a different type and are not assignable, so just ignore it
}
}
// <7> 最差,使用 Java Type 为 null 进行注册
if (!mappedTypeFound) {
register((Class<T>) null, typeHandler);
}
}
// TypeHandlerRegistry.java
public void register(JdbcType jdbcType, TypeHandler<?> handler) {
JDBC_TYPE_HANDLER_MAP.put(jdbcType, handler);
}
private <T> TypeHandler<T> getTypeHandler(Type type, JdbcType jdbcType) {
// 忽略 ParamMap 的情况
if (ParamMap.class.equals(type)) {
return null;
}
// <1> 获得 Java Type 对应的 TypeHandler 集合
Map<JdbcType, TypeHandler<?>> jdbcHandlerMap = getJdbcHandlerMap(type);
TypeHandler<?> handler = null;
if (jdbcHandlerMap != null) {
// <2.1> 优先,使用 jdbcType 获取对应的 TypeHandler
handler = jdbcHandlerMap.get(jdbcType);
// <2.2> 其次,使用 null 获取对应的 TypeHandler ,可以认为是默认的 TypeHandler
if (handler == null) {
handler = jdbcHandlerMap.get(null);
}
// <2.3> 最差,从 TypeHandler 集合中选择一个唯一的 TypeHandler
if (handler == null) {
// #591
handler = pickSoleHandler(jdbcHandlerMap);
}
}
// type drives generics here
return (TypeHandler<T>) handler;
}
private Map<JdbcType, TypeHandler<?>> getJdbcHandlerMap(Type type) {
// <1.1> 获得 Java Type 对应的 TypeHandler 集合
Map<JdbcType, TypeHandler<?>> jdbcHandlerMap = TYPE_HANDLER_MAP.get(type);
// <1.2> 如果为 NULL_TYPE_HANDLER_MAP ,意味着为空,直接返回
if (NULL_TYPE_HANDLER_MAP.equals(jdbcHandlerMap)) {
return null;
}
// <1.3> 如果找不到
if (jdbcHandlerMap == null && type instanceof Class) {
Class<?> clazz = (Class<?>) type;
// 枚举类型
if (clazz.isEnum()) {
// 获得父类对应的 TypeHandler 集合
jdbcHandlerMap = getJdbcHandlerMapForEnumInterfaces(clazz, clazz);
// 如果找不到
if (jdbcHandlerMap == null) {
// 注册 defaultEnumTypeHandler ,并使用它
register(clazz, getInstance(clazz, defaultEnumTypeHandler));
// 返回结果
return TYPE_HANDLER_MAP.get(clazz);
}
// 非枚举类型
} else {
// 获得父类对应的 TypeHandler 集合
jdbcHandlerMap = getJdbcHandlerMapForSuperclass(clazz);
}
}
// <1.4> 如果结果为空,设置为 NULL_TYPE_HANDLER_MAP ,提升查找速度,避免二次查找
TYPE_HANDLER_MAP.put(type, jdbcHandlerMap == null ? NULL_TYPE_HANDLER_MAP : jdbcHandlerMap);
// 返回结果
return jdbcHandlerMap;
}
private Map<JdbcType, TypeHandler<?>> getJdbcHandlerMapForEnumInterfaces(Class<?> clazz, Class<?> enumClazz) {
// 遍历枚举类的所有接口
for (Class<?> iface : clazz.getInterfaces()) {
// 获得该接口对应的 jdbcHandlerMap 集合
Map<JdbcType, TypeHandler<?>> jdbcHandlerMap = TYPE_HANDLER_MAP.get(iface);
// 为空,递归 getJdbcHandlerMapForEnumInterfaces 方法,继续从父类对应的 TypeHandler 集合
if (jdbcHandlerMap == null) {
jdbcHandlerMap = getJdbcHandlerMapForEnumInterfaces(iface, enumClazz);
}
// 如果找到,则从 jdbcHandlerMap 初始化中 newMap 中,并进行返回
if (jdbcHandlerMap != null) {
// Found a type handler regsiterd to a super interface
HashMap<JdbcType, TypeHandler<?>> newMap = new HashMap<>();
for (Entry<JdbcType, TypeHandler<?>> entry : jdbcHandlerMap.entrySet()) {
// Create a type handler instance with enum type as a constructor arg
newMap.put(entry.getKey(), getInstance(enumClazz, entry.getValue().getClass()));
}
return newMap;
}
}
// 找不到,则返回 null
return null;
}
// TypeHandlerRegistry.java
private Map<JdbcType, TypeHandler<?>> getJdbcHandlerMapForSuperclass(Class<?> clazz) {
// 获得父类
Class<?> superclass = clazz.getSuperclass();
// 不存在非 Object 的父类,返回 null
if (superclass == null || Object.class.equals(superclass)) {
return null;
}
// 获得父类对应的 TypeHandler 集合
Map<JdbcType, TypeHandler<?>> jdbcHandlerMap = TYPE_HANDLER_MAP.get(superclass);
// 找到,则直接返回
if (jdbcHandlerMap != null) {
return jdbcHandlerMap;
// 找不到,则递归 getJdbcHandlerMapForSuperclass 方法,继续获得父类对应的 TypeHandler 集合
} else {
return getJdbcHandlerMapForSuperclass(superclass);
}
}
private TypeHandler<?> pickSoleHandler(Map<JdbcType, TypeHandler<?>> jdbcHandlerMap) {
TypeHandler<?> soleHandler = null;
for (TypeHandler<?> handler : jdbcHandlerMap.values()) {
// 选择一个
if (soleHandler == null) {
soleHandler = handler;
// 如果还有,并且不同类,那么不好选择,所以返回 null
} else if (!handler.getClass().equals(soleHandler.getClass())) {
// More than one type handlers registered.
return null;
}
}
return soleHandler;
}
org.apache.ibatis.type.TypeAliasRegistry
,类型与别名的注册表。通过别名,我们在 Mapper XML 中的 resultType
和 parameterType
属性,直接使用,而不用写全类名。public class TypeAliasRegistry {
// 类型与别名的映射
private final Map<String, Class<?>> typeAliases = new HashMap<>();
public TypeAliasRegistry() {
registerAlias("string", String.class);
registerAlias("byte", Byte.class);
registerAlias("long", Long.class);
registerAlias("short", Short.class);
registerAlias("int", Integer.class);
registerAlias("integer", Integer.class);
registerAlias("double", Double.class);
registerAlias("float", Float.class);
registerAlias("boolean", Boolean.class);
registerAlias("byte[]", Byte[].class);
registerAlias("long[]", Long[].class);
registerAlias("short[]", Short[].class);
registerAlias("int[]", Integer[].class);
registerAlias("integer[]", Integer[].class);
registerAlias("double[]", Double[].class);
registerAlias("float[]", Float[].class);
registerAlias("boolean[]", Boolean[].class);
registerAlias("_byte", byte.class);
registerAlias("_long", long.class);
registerAlias("_short", short.class);
registerAlias("_int", int.class);
registerAlias("_integer", int.class);
registerAlias("_double", double.class);
registerAlias("_float", float.class);
registerAlias("_boolean", boolean.class);
registerAlias("_byte[]", byte[].class);
registerAlias("_long[]", long[].class);
registerAlias("_short[]", short[].class);
registerAlias("_int[]", int[].class);
registerAlias("_integer[]", int[].class);
registerAlias("_double[]", double[].class);
registerAlias("_float[]", float[].class);
registerAlias("_boolean[]", boolean[].class);
registerAlias("date", Date.class);
registerAlias("decimal", BigDecimal.class);
registerAlias("bigdecimal", BigDecimal.class);
registerAlias("biginteger", BigInteger.class);
registerAlias("object", Object.class);
registerAlias("date[]", Date[].class);
registerAlias("decimal[]", BigDecimal[].class);
registerAlias("bigdecimal[]", BigDecimal[].class);
registerAlias("biginteger[]", BigInteger[].class);
registerAlias("object[]", Object[].class);
registerAlias("map", Map.class);
registerAlias("hashmap", HashMap.class);
registerAlias("list", List.class);
registerAlias("arraylist", ArrayList.class);
registerAlias("collection", Collection.class);
registerAlias("iterator", Iterator.class);
registerAlias("ResultSet", ResultSet.class);
}
@SuppressWarnings("unchecked")
// throws class cast exception as well if types cannot be assigned
public <T> Class<T> resolveAlias(String string) {
try {
if (string == null) {
return null;
}
// issue #748
String key = string.toLowerCase(Locale.ENGLISH);
Class<T> value;
if (typeAliases.containsKey(key)) {
value = (Class<T>) typeAliases.get(key);
} else {
value = (Class<T>) Resources.classForName(string);
}
return value;
} catch (ClassNotFoundException e) {
throw new TypeException("Could not resolve type alias '" + string + "'. Cause: " + e, e);
}
}
// 注册包的类
public void registerAliases(String packageName) {
registerAliases(packageName, Object.class);
}
// 注册类
public void registerAliases(String packageName, Class<?> superType) {
ResolverUtil<Class<?>> resolverUtil = new ResolverUtil<>();
resolverUtil.find(new ResolverUtil.IsA(superType), packageName);
Set<Class<? extends Class<?>>> typeSet = resolverUtil.getClasses();
for (Class<?> type : typeSet) {
// Ignore inner classes and interfaces (including package-info.java)
// Skip also inner classes. See issue #6
if (!type.isAnonymousClass() && !type.isInterface() && !type.isMemberClass()) {
registerAlias(type);
}
}
}
// 注册指定类
public void registerAlias(Class<?> type) {
String alias = type.getSimpleName();
Alias aliasAnnotation = type.getAnnotation(Alias.class);
if (aliasAnnotation != null) {
alias = aliasAnnotation.value();
}
registerAlias(alias, type);
}
public void registerAlias(String alias, Class<?> value) {
if (alias == null) {
throw new TypeException("The parameter alias cannot be null");
}
// issue #748
String key = alias.toLowerCase(Locale.ENGLISH);
if (typeAliases.containsKey(key) && typeAliases.get(key) != null && !typeAliases.get(key).equals(value)) {
throw new TypeException("The alias '" + alias + "' is already mapped to the value '" + typeAliases.get(key).getName() + "'.");
}
typeAliases.put(key, value);
}
public void registerAlias(String alias, String value) {
try {
registerAlias(alias, Resources.classForName(value));
} catch (ClassNotFoundException e) {
throw new TypeException("Error registering type alias " + alias + " for " + value + ". Cause: " + e, e);
}
}
/**
* Gets the type aliases.
*
* @return the type aliases
* @since 3.2.2
*/
public Map<String, Class<?>> getTypeAliases() {
return Collections.unmodifiableMap(typeAliases);
}
}
org.apache.ibatis.type.SimpleTypeRegistry
,简单类型注册表public class SimpleTypeRegistry {
// 简单类型集合
private static final Set<Class<?>> SIMPLE_TYPE_SET = new HashSet<>();
// 初始化
static {
SIMPLE_TYPE_SET.add(String.class);
SIMPLE_TYPE_SET.add(Byte.class);
SIMPLE_TYPE_SET.add(Short.class);
SIMPLE_TYPE_SET.add(Character.class);
SIMPLE_TYPE_SET.add(Integer.class);
SIMPLE_TYPE_SET.add(Long.class);
SIMPLE_TYPE_SET.add(Float.class);
SIMPLE_TYPE_SET.add(Double.class);
SIMPLE_TYPE_SET.add(Boolean.class);
SIMPLE_TYPE_SET.add(Date.class);
SIMPLE_TYPE_SET.add(Class.class);
SIMPLE_TYPE_SET.add(BigInteger.class);
SIMPLE_TYPE_SET.add(BigDecimal.class);
}
private SimpleTypeRegistry() {
// Prevent Instantiation
}
/*
* Tells us if the class passed in is a known common type
*
* @param clazz The class to check
* @return True if the class is known
*/
public static boolean isSimpleType(Class<?> clazz) {
return SIMPLE_TYPE_SET.contains(clazz);
}
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。