Browse Source

统一通用枚举处理.

nieqiuqiu 6 years ago
parent
commit
b1a476e696

+ 5 - 3
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/handlers/EnumAnnotationTypeHandler.java

@@ -42,7 +42,9 @@ import java.util.concurrent.ConcurrentHashMap;
  *
  * @author yuxiaobin
  * @date 2018-08-30
+ * @deprecated  3.0.8 {@link com.baomidou.mybatisplus.extension.handlers.EnumTypeHandler}
  */
+@Deprecated
 public class EnumAnnotationTypeHandler<E extends Enum<E>> extends BaseTypeHandler<E> {
 
     private final Class<E> type;
@@ -65,7 +67,7 @@ public class EnumAnnotationTypeHandler<E extends Enum<E>> extends BaseTypeHandle
 
     @Override
     public void setNonNullParameter(PreparedStatement ps, int i, Enum parameter, JdbcType jdbcType) throws SQLException {
-        Method method = getField(type);
+        Method method = getMethod(type);
         try {
             method.setAccessible(true);
             if (jdbcType == null) {
@@ -90,7 +92,7 @@ public class EnumAnnotationTypeHandler<E extends Enum<E>> extends BaseTypeHandle
         if (s == null) {
             return null;
         }
-        return EnumUtils.valueOf(type, s, getField(type));
+        return EnumUtils.valueOf(type, s, getMethod(type));
     }
 
     @Override
@@ -107,7 +109,7 @@ public class EnumAnnotationTypeHandler<E extends Enum<E>> extends BaseTypeHandle
         return clazz.isEnum() ? Arrays.stream(clazz.getDeclaredFields()).filter(field -> field.isAnnotationPresent(EnumValue.class)).findFirst() : Optional.empty();
     }
 
-    private Method getField(Class<?> clazz) {
+    private Method getMethod(Class<?> clazz) {
         return Optional.ofNullable(TABLE_FIELD_OF_ENUM_TYPES.get(type)).orElseGet(() -> {
             Field field = dealEnumType(clazz).orElseThrow(() -> new IllegalArgumentException("当前[" + type.getName() + "]枚举类未找到标有@EnumValue注解的字段"));
             Method method = ReflectionKit.getMethod(clazz, field);

+ 54 - 13
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/handlers/EnumTypeHandler.java

@@ -15,17 +15,28 @@
  */
 package com.baomidou.mybatisplus.extension.handlers;
 
+import com.baomidou.mybatisplus.annotation.EnumValue;
 import com.baomidou.mybatisplus.core.enums.IEnum;
 import com.baomidou.mybatisplus.core.toolkit.EnumUtils;
+import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils;
+import com.baomidou.mybatisplus.core.toolkit.ReflectionKit;
 
+import org.apache.ibatis.logging.Log;
+import org.apache.ibatis.logging.LogFactory;
 import org.apache.ibatis.type.BaseTypeHandler;
 import org.apache.ibatis.type.JdbcType;
 
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.sql.CallableStatement;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.SQLException;
+import java.util.Arrays;
+import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.ConcurrentHashMap;
 
 /**
  * 自定义枚举属性转换器
@@ -33,7 +44,11 @@ import java.sql.SQLException;
  * @author hubin
  * @since 2017-10-11
  */
-public class EnumTypeHandler<E extends Enum<?> & IEnum> extends BaseTypeHandler<IEnum> {
+public class EnumTypeHandler<E extends Enum<?>> extends BaseTypeHandler<Enum> {
+
+    private static final Log LOGGER = LogFactory.getLog(EnumTypeHandler.class);
+
+    private static final Map<Class<?>, Method> TABLE_FIELD_OF_ENUM_TYPES = new ConcurrentHashMap<>();
 
     private Class<E> type;
 
@@ -43,24 +58,33 @@ public class EnumTypeHandler<E extends Enum<?> & IEnum> extends BaseTypeHandler<
         if (type == null) {
             throw new IllegalArgumentException("Type argument cannot be null");
         }
-        if (!IEnum.class.isAssignableFrom(type)) {
-            throw new IllegalArgumentException("当前[" + type.getName() + "]枚举类未实现" + IEnum.class.getName() + "接口");
-        }
         this.type = type;
-        try {
-            method = type.getMethod("getValue");
-        } catch (NoSuchMethodException e) {
-            throw new IllegalArgumentException("当前[" + type.getName() + "]枚举类未找到getValue方法");
+        if (IEnum.class.isAssignableFrom(type)) {
+            try {
+                method = type.getMethod("getValue");
+            } catch (NoSuchMethodException e) {
+                throw new IllegalArgumentException("当前[" + type.getName() + "]枚举类未找到getValue方法");
+            }
+        } else {
+            method = getMethod(type);
         }
     }
 
     @Override
-    public void setNonNullParameter(PreparedStatement ps, int i, IEnum parameter, JdbcType jdbcType)
+    public void setNonNullParameter(PreparedStatement ps, int i, Enum parameter, JdbcType jdbcType)
         throws SQLException {
-        if (jdbcType == null) {
-            ps.setObject(i, parameter.getValue());
-        } else {
-            ps.setObject(i, parameter.getValue(), jdbcType.TYPE_CODE);
+        try {
+            method.setAccessible(true);
+            if (jdbcType == null) {
+                ps.setObject(i, method.invoke(parameter));
+            } else {
+                // see r3589
+                ps.setObject(i, method.invoke(parameter), jdbcType.TYPE_CODE);
+            }
+        } catch (IllegalAccessException e) {
+            LOGGER.error("unrecognized jdbcType, failed to set StringValue for type=" + parameter);
+        } catch (InvocationTargetException e) {
+            throw ExceptionUtils.mpe("Error: NoSuchMethod in %s.  Cause:", e, type.getName());
         }
     }
 
@@ -87,4 +111,21 @@ public class EnumTypeHandler<E extends Enum<?> & IEnum> extends BaseTypeHandler<
         }
         return EnumUtils.valueOf(type, cs.getObject(columnIndex), method);
     }
+
+    public static Optional<Field> dealEnumType(Class<?> clazz) {
+        return clazz.isEnum() ? Arrays.stream(clazz.getDeclaredFields()).filter(field -> field.isAnnotationPresent(EnumValue.class)).findFirst() : Optional.empty();
+    }
+
+    public static void addEnumType(Class<?> clazz, Method method) {
+        TABLE_FIELD_OF_ENUM_TYPES.put(clazz, method);
+    }
+
+    private Method getMethod(Class<?> clazz) {
+        return Optional.ofNullable(TABLE_FIELD_OF_ENUM_TYPES.get(type)).orElseGet(() -> {
+            Field field = dealEnumType(clazz).orElseThrow(() -> new IllegalArgumentException("当前[" + type.getName() + "]枚举类未找到标有@EnumValue注解的字段"));
+            Method method = ReflectionKit.getMethod(clazz, field);
+            addEnumType(clazz, method);
+            return method;
+        });
+    }
 }

+ 3 - 3
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/spring/MybatisSqlSessionFactoryBean.java

@@ -533,10 +533,10 @@ public class MybatisSqlSessionFactoryBean implements FactoryBean<SqlSessionFacto
                         typeHandlerRegistry.register(cls, EnumTypeHandler.class);
                     } else {
                         // 注解方式
-                        Optional<Field> optional = EnumAnnotationTypeHandler.dealEnumType(cls);
+                        Optional<Field> optional = EnumTypeHandler.dealEnumType(cls);
                         if (optional.isPresent()) {
-                            EnumAnnotationTypeHandler.addEnumType(cls, ReflectionKit.getMethod(cls, optional.get()));
-                            typeHandlerRegistry.register(cls, EnumAnnotationTypeHandler.class);
+                            EnumTypeHandler.addEnumType(cls, ReflectionKit.getMethod(cls, optional.get()));
+                            typeHandlerRegistry.register(cls, EnumTypeHandler.class);
                         }
                     }
                 }