|
@@ -3,6 +3,7 @@ package com.chelvc.framework.database.interceptor;
|
|
|
import java.lang.reflect.Field;
|
|
|
import java.lang.reflect.ParameterizedType;
|
|
|
import java.lang.reflect.Type;
|
|
|
+import java.util.Collection;
|
|
|
import java.util.List;
|
|
|
import java.util.Map;
|
|
|
import java.util.concurrent.atomic.AtomicLong;
|
|
@@ -41,6 +42,7 @@ import com.google.common.collect.Maps;
|
|
|
import javassist.ClassPool;
|
|
|
import javassist.CtClass;
|
|
|
import javassist.CtConstructor;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
import org.apache.ibatis.parsing.XNode;
|
|
|
import org.apache.ibatis.type.UnknownTypeHandler;
|
|
|
import org.w3c.dom.Document;
|
|
@@ -52,6 +54,7 @@ import org.w3c.dom.Element;
|
|
|
* @author Woody
|
|
|
* @date 2024/4/6
|
|
|
*/
|
|
|
+@Slf4j
|
|
|
public class JsonHandlerConfigureInterceptor extends MybatisConfigureInterceptor {
|
|
|
/**
|
|
|
* JSON类型处理器计数器
|
|
@@ -63,6 +66,17 @@ public class JsonHandlerConfigureInterceptor extends MybatisConfigureInterceptor
|
|
|
*/
|
|
|
private final Map<Type, Class<?>> handlers = Maps.newConcurrentMap();
|
|
|
|
|
|
+ /**
|
|
|
+ * 判断是否是元类型
|
|
|
+ *
|
|
|
+ * @param clazz 对象类型
|
|
|
+ * @return true/false
|
|
|
+ */
|
|
|
+ private boolean isMetaType(Class<?> clazz) {
|
|
|
+ return DatabaseContextHolder.isTypeHandlerRegistered(clazz) || Map.class.isAssignableFrom(clazz)
|
|
|
+ || Collection.class.isAssignableFrom(clazz);
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 绑定字段JSON类型处理器
|
|
|
*
|
|
@@ -174,6 +188,9 @@ public class JsonHandlerConfigureInterceptor extends MybatisConfigureInterceptor
|
|
|
* @return true/false
|
|
|
*/
|
|
|
private boolean isJsonHandlerConfigurable(Class<?> clazz) {
|
|
|
+ if (this.isMetaType(clazz)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
Reference<Boolean> configurable = new Reference<>();
|
|
|
ObjectUtils.iterateFields(clazz, (i, field) -> {
|
|
|
if (this.isJsonHandlerConfigurable(field)) {
|
|
@@ -204,14 +221,14 @@ public class JsonHandlerConfigureInterceptor extends MybatisConfigureInterceptor
|
|
|
*/
|
|
|
private Class<?> getSelectResultType(XNode node) {
|
|
|
String type = node.getStringAttribute("resultType");
|
|
|
- if (StringUtils.isEmpty(type)) {
|
|
|
- return null;
|
|
|
- }
|
|
|
- try {
|
|
|
- return Class.forName(type);
|
|
|
- } catch (ClassNotFoundException e) {
|
|
|
- throw new RuntimeException(e);
|
|
|
+ if (StringUtils.notEmpty(type)) {
|
|
|
+ try {
|
|
|
+ return Class.forName(type);
|
|
|
+ } catch (ClassNotFoundException e) {
|
|
|
+ log.warn("Result type class load failed: {}", e.getMessage());
|
|
|
+ }
|
|
|
}
|
|
|
+ return null;
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -221,11 +238,15 @@ public class JsonHandlerConfigureInterceptor extends MybatisConfigureInterceptor
|
|
|
* @return 对象类型
|
|
|
*/
|
|
|
private Class<?> getResultMappingType(XNode node) {
|
|
|
- try {
|
|
|
- return Class.forName(node.getStringAttribute("type"));
|
|
|
- } catch (ClassNotFoundException e) {
|
|
|
- throw new RuntimeException(e);
|
|
|
+ String type = node.getStringAttribute("type");
|
|
|
+ if (StringUtils.notEmpty(type)) {
|
|
|
+ try {
|
|
|
+ return Class.forName(type);
|
|
|
+ } catch (ClassNotFoundException e) {
|
|
|
+ log.warn("Result map class load failed: {}", e.getMessage());
|
|
|
+ }
|
|
|
}
|
|
|
+ return null;
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -267,20 +288,23 @@ public class JsonHandlerConfigureInterceptor extends MybatisConfigureInterceptor
|
|
|
// 设置已有resultMap的json类型处理器
|
|
|
List<XNode> maps = mapper.evalNodes("resultMap");
|
|
|
if (ObjectUtils.notEmpty(maps)) {
|
|
|
- maps.forEach(map -> {
|
|
|
+ for (XNode map : maps) {
|
|
|
Class<?> clazz = this.getResultMappingType(map);
|
|
|
+ if (clazz == null || this.isMetaType(clazz)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
for (XNode child : map.getChildren()) {
|
|
|
// 判断当前是有存在typeHandler,如果不存在且字段满足配置json类型处理器条件,则自动绑定json类型处理器
|
|
|
if (StringUtils.isEmpty(child.getStringAttribute("typeHandler"))) {
|
|
|
String property = child.getStringAttribute("property");
|
|
|
- Field field = ObjectUtils.getField(clazz, property);
|
|
|
- if (this.isJsonHandlerConfigurable(field)) {
|
|
|
+ Field field = ObjectUtils.lookupField(clazz, property);
|
|
|
+ if (field != null && this.isJsonHandlerConfigurable(field)) {
|
|
|
Class<?> handler = this.lookupJsonHandlerClass(field);
|
|
|
((Element) child.getNode()).setAttribute("typeHandler", handler.getName());
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- });
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
// 设置resultType对应的resultMap,并将原来的resultType替换成resultMap
|
|
@@ -288,20 +312,24 @@ public class JsonHandlerConfigureInterceptor extends MybatisConfigureInterceptor
|
|
|
List<XNode> selects = mapper.evalNodes("select");
|
|
|
if (ObjectUtils.notEmpty(selects)) {
|
|
|
Map<Class<?>, Element> cache = Maps.newHashMap();
|
|
|
- selects.forEach(select -> {
|
|
|
+ for (XNode select : selects) {
|
|
|
// 判断resultType是否可配置json类型处理器
|
|
|
Class<?> clazz = this.getSelectResultType(select);
|
|
|
- if (clazz != null && this.isJsonHandlerConfigurable(clazz)) {
|
|
|
- // 构建并注册resultMap
|
|
|
- Element map = cache.computeIfAbsent(clazz, c -> this.initializeResultMapping(document, clazz));
|
|
|
- mapper.getNode().appendChild(map);
|
|
|
+ try {
|
|
|
+ if (clazz != null && this.isJsonHandlerConfigurable(clazz)) {
|
|
|
+ // 构建并注册resultMap
|
|
|
+ Element map = cache.computeIfAbsent(clazz, c -> this.initializeResultMapping(document, clazz));
|
|
|
+ mapper.getNode().appendChild(map);
|
|
|
|
|
|
- // 用户新生成的resultMap替换resultType
|
|
|
- Element element = (Element) select.getNode();
|
|
|
- element.removeAttribute("resultType");
|
|
|
- element.setAttribute("resultMap", map.getAttribute("id"));
|
|
|
+ // 用户新生成的resultMap替换resultType
|
|
|
+ Element element = (Element) select.getNode();
|
|
|
+ element.removeAttribute("resultType");
|
|
|
+ element.setAttribute("resultMap", map.getAttribute("id"));
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
}
|
|
|
- });
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|