|
@@ -104,8 +104,10 @@ import javassist.NotFoundException;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
import org.apache.ibatis.parsing.XNode;
|
|
|
import org.apache.ibatis.reflection.TypeParameterResolver;
|
|
|
+import org.apache.ibatis.session.Configuration;
|
|
|
import org.apache.ibatis.type.JdbcType;
|
|
|
import org.apache.ibatis.type.TypeAliasRegistry;
|
|
|
+import org.apache.ibatis.type.TypeHandler;
|
|
|
import org.apache.ibatis.type.UnknownTypeHandler;
|
|
|
import org.w3c.dom.Document;
|
|
|
import org.w3c.dom.Element;
|
|
@@ -120,14 +122,18 @@ import org.w3c.dom.NodeList;
|
|
|
@Slf4j
|
|
|
public class TypeHandlerConfigurer extends MybatisConfigurer {
|
|
|
/**
|
|
|
- * JSON类型/处理器映射表
|
|
|
+ * 内置的别名/对象类型映射表
|
|
|
*/
|
|
|
- private final Map<Type, Class<?>> handlers = Maps.newConcurrentMap();
|
|
|
+ private final Map<String, Class<?>> aliases = new TypeAliasRegistry().getTypeAliases();
|
|
|
|
|
|
/**
|
|
|
- * 内置的别名/对象类型映射表
|
|
|
+ * JSON类型/处理器映射表
|
|
|
*/
|
|
|
- private final Map<String, Class<?>> aliases = new TypeAliasRegistry().getTypeAliases();
|
|
|
+ private final Map<Type, Class<? extends TypeHandler<?>>> handlers = Maps.newConcurrentMap();
|
|
|
+
|
|
|
+ public TypeHandlerConfigurer(Configuration configuration) {
|
|
|
+ super(configuration);
|
|
|
+ }
|
|
|
|
|
|
/**
|
|
|
* 将对象名称转换成类对象
|
|
@@ -236,12 +242,19 @@ public class TypeHandlerConfigurer extends MybatisConfigurer {
|
|
|
* @param clazz 对象类型
|
|
|
* @param field 表字段信息
|
|
|
*/
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
private void bindTypeHandler(Class<?> clazz, TableFieldInfo field) {
|
|
|
- Class<?> handler = this.lookupTypeHandlerClass(clazz, field.getField(), field.getTypeHandler());
|
|
|
+ Class<? extends TypeHandler<?>> handler =
|
|
|
+ this.lookupTypeHandlerClass(clazz, field.getField(), field.getTypeHandler());
|
|
|
if (handler != null) {
|
|
|
ObjectUtils.setValue(field, "typeHandler", handler);
|
|
|
String el = ObjectUtils.getValue(field, "el") + ",typeHandler=" + handler.getName();
|
|
|
ObjectUtils.setValue(field, "el", el);
|
|
|
+
|
|
|
+ // 注册类型TypeHandler实例
|
|
|
+ this.configuration.getTypeHandlerRegistry().register(
|
|
|
+ (Class<Object>) field.getField().getType(), DatabaseContextHolder.initializeTypeHandler(handler)
|
|
|
+ );
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -251,7 +264,7 @@ public class TypeHandlerConfigurer extends MybatisConfigurer {
|
|
|
* @param type 对象类型
|
|
|
* @return 类型处理器对象
|
|
|
*/
|
|
|
- private Class<?> lookupJsonHandlerClass(Type type) {
|
|
|
+ private Class<? extends TypeHandler<?>> lookupJsonHandlerClass(Type type) {
|
|
|
if (ObjectUtils.isOnlyMap(type)) {
|
|
|
return MapTypeHandler.class;
|
|
|
} else if (ObjectUtils.isOnlySet(type)) {
|
|
@@ -353,7 +366,9 @@ public class TypeHandlerConfigurer extends MybatisConfigurer {
|
|
|
* @param handler 当前类型处理器对象
|
|
|
* @return 类型处理器对象
|
|
|
*/
|
|
|
- private Class<?> lookupTypeHandlerClass(Class<?> clazz, Field field, Class<?> handler) {
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
+ private Class<? extends TypeHandler<?>> lookupTypeHandlerClass(Class<?> clazz, Field field,
|
|
|
+ Class<? extends TypeHandler<?>> handler) {
|
|
|
// 排除忽略字段
|
|
|
TableField annotation = field.getAnnotation(TableField.class);
|
|
|
if (annotation != null && !annotation.exist()) {
|
|
@@ -363,7 +378,8 @@ public class TypeHandlerConfigurer extends MybatisConfigurer {
|
|
|
// 如果当前类型处理器不存在,则继续查找@TableField注解中的类型处理器,如果仍不存在则尝试使用JSON类型处理器
|
|
|
Type type = TypeParameterResolver.resolveFieldType(field, clazz);
|
|
|
Class<?> model = ObjectUtils.type2class(type);
|
|
|
- if (((handler == null && (handler = ObjectUtils.ifNull(annotation, TableField::typeHandler)) == null)
|
|
|
+ if (((handler == null && (handler = (Class<? extends TypeHandler<?>>)
|
|
|
+ ObjectUtils.ifNull(annotation, TableField::typeHandler)) == null)
|
|
|
|| handler == UnknownTypeHandler.class || handler == JacksonTypeHandler.class)
|
|
|
&& !this.isTypeHandlerRegistered(model)) {
|
|
|
handler = this.lookupJsonHandlerClass(type);
|
|
@@ -391,7 +407,8 @@ public class TypeHandlerConfigurer extends MybatisConfigurer {
|
|
|
* @param type 对象类型
|
|
|
* @return 类型处理器对象
|
|
|
*/
|
|
|
- private Class<?> initializeJsonHandlerClass(Type type) {
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
+ private Class<? extends TypeHandler<?>> initializeJsonHandlerClass(Type type) {
|
|
|
ClassPool pool = ClassPool.getDefault();
|
|
|
CtClass handler = pool.makeClass(StringUtils.uuid());
|
|
|
try {
|
|
@@ -399,7 +416,7 @@ public class TypeHandlerConfigurer extends MybatisConfigurer {
|
|
|
CtConstructor constructor = new CtConstructor(new CtClass[]{}, handler);
|
|
|
constructor.setBody(String.format("{super(%s);}", ObjectUtils.analyse(type)));
|
|
|
handler.addConstructor(constructor);
|
|
|
- return handler.toClass(this.getClass().getClassLoader(), null);
|
|
|
+ return (Class<? extends TypeHandler<?>>) handler.toClass(this.getClass().getClassLoader(), null);
|
|
|
} catch (NotFoundException | CannotCompileException e) {
|
|
|
throw new RuntimeException(e);
|
|
|
}
|
|
@@ -412,7 +429,8 @@ public class TypeHandlerConfigurer extends MybatisConfigurer {
|
|
|
* @param superclass 处理器父类
|
|
|
* @return 类型处理器对象
|
|
|
*/
|
|
|
- private Class<?> initializeSensitiveHandlerClass(Class<?> model, Class<?> superclass) {
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
+ private Class<? extends TypeHandler<?>> initializeSensitiveHandlerClass(Class<?> model, Class<?> superclass) {
|
|
|
if (superclass == null) {
|
|
|
return SensitiveTypeHandler.class;
|
|
|
}
|
|
@@ -455,7 +473,7 @@ public class TypeHandlerConfigurer extends MybatisConfigurer {
|
|
|
model.getName(), method, CallableStatement.class.getName(), SQLException.class.getName(),
|
|
|
method, CallableStringDecrypter.class.getName()
|
|
|
), handler));
|
|
|
- return handler.toClass(this.getClass().getClassLoader(), null);
|
|
|
+ return (Class<? extends TypeHandler<?>>) handler.toClass(this.getClass().getClassLoader(), null);
|
|
|
} catch (NotFoundException | CannotCompileException e) {
|
|
|
throw new RuntimeException(e);
|
|
|
}
|
|
@@ -488,6 +506,7 @@ public class TypeHandlerConfigurer extends MybatisConfigurer {
|
|
|
* @param field 对象字段
|
|
|
* @param consumer resultMap元素回调函数
|
|
|
*/
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
private void initializeResultMapping(Document document, Class<?> clazz, Field field, Consumer<Element> consumer) {
|
|
|
// 排除主键字段
|
|
|
if (field.isAnnotationPresent(TableId.class)) {
|
|
@@ -495,7 +514,7 @@ public class TypeHandlerConfigurer extends MybatisConfigurer {
|
|
|
}
|
|
|
|
|
|
// 排除不需要TypeHandler的字段
|
|
|
- Class<?> handler = this.lookupTypeHandlerClass(clazz, field, null);
|
|
|
+ Class<? extends TypeHandler<?>> handler = this.lookupTypeHandlerClass(clazz, field, null);
|
|
|
if (handler == null) {
|
|
|
return;
|
|
|
}
|
|
@@ -524,9 +543,15 @@ public class TypeHandlerConfigurer extends MybatisConfigurer {
|
|
|
child.setAttribute("typeHandler", handler.getName());
|
|
|
consumer.accept(child);
|
|
|
});
|
|
|
+
|
|
|
+ // 注册类型TypeHandler实例
|
|
|
+ this.configuration.getTypeHandlerRegistry().register(
|
|
|
+ (Class<Object>) field.getType(), DatabaseContextHolder.initializeTypeHandler(handler)
|
|
|
+ );
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
public void intercept(XNode mapper) {
|
|
|
// 设置已有resultMap的类型处理器
|
|
|
Document document = mapper.getNode().getOwnerDocument();
|
|
@@ -547,9 +572,15 @@ public class TypeHandlerConfigurer extends MybatisConfigurer {
|
|
|
}
|
|
|
|
|
|
// 重置字段类型处理器
|
|
|
- Class<?> handler = this.name2class(child.getStringAttribute("typeHandler"));
|
|
|
+ Class<? extends TypeHandler<?>> handler =
|
|
|
+ (Class<? extends TypeHandler<?>>) this.name2class(child.getStringAttribute("typeHandler"));
|
|
|
if ((handler = this.lookupTypeHandlerClass(clazz, field, handler)) != null) {
|
|
|
((Element) child.getNode()).setAttribute("typeHandler", handler.getName());
|
|
|
+
|
|
|
+ // 注册类型TypeHandler实例
|
|
|
+ this.configuration.getTypeHandlerRegistry().register(
|
|
|
+ (Class<Object>) field.getType(), DatabaseContextHolder.initializeTypeHandler(handler)
|
|
|
+ );
|
|
|
}
|
|
|
if (StringUtils.isEmpty(child.getStringAttribute("typeHandler"))) {
|
|
|
continue;
|