Browse Source

优化一下枚举处理器.

聂秋秋 5 years ago
parent
commit
10fa454904

+ 4 - 1
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/EnumUtils.java

@@ -27,7 +27,9 @@ import java.util.Objects;
  *
  * @author hubin
  * @since 2017-10-11
+ * @deprecated 3.2.1
  */
+@Deprecated
 public class EnumUtils {
 
     /**
@@ -37,8 +39,9 @@ public class EnumUtils {
      * @param value     枚举值
      * @param method    取值方法
      * @param <E>       对应枚举
-     * @return
+     * @return @deprecated 3.2.1
      */
+    @Deprecated
     public static <E extends Enum<?>> E valueOf(Class<E> enumClass, Object value, Method method) {
         E[] es = enumClass.getEnumConstants();
         for (E e : es) {

+ 54 - 37
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/handlers/MybatisEnumTypeHandler.java

@@ -17,23 +17,21 @@ 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.reflection.*;
+import org.apache.ibatis.reflection.invoker.Invoker;
 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.math.BigDecimal;
 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.Objects;
 import java.util.Optional;
 import java.util.concurrent.ConcurrentHashMap;
 
@@ -45,49 +43,39 @@ import java.util.concurrent.ConcurrentHashMap;
  */
 public class MybatisEnumTypeHandler<E extends Enum<?>> extends BaseTypeHandler<Enum<?>> {
 
-    private static final Log LOGGER = LogFactory.getLog(MybatisEnumTypeHandler.class);
-    
-    private static final Map<Class<?>, Method> TABLE_METHOD_OF_ENUM_TYPES = new ConcurrentHashMap<>();
-    
+    private static ReflectorFactory reflectorFactory = new DefaultReflectorFactory();
+
+    private static final Map<String, String> TABLE_METHOD_OF_ENUM_TYPES = new ConcurrentHashMap<>();
+
     private final Class<E> type;
-    
-    private final Method method;
+
+    private Invoker invoker;
 
     public MybatisEnumTypeHandler(Class<E> type) {
         if (type == null) {
             throw new IllegalArgumentException("Type argument cannot be null");
         }
         this.type = type;
-        if (IEnum.class.isAssignableFrom(type)) {
-            try {
-                this.method = type.getMethod("getValue");
-            } catch (NoSuchMethodException e) {
-                throw new IllegalArgumentException(String.format("NoSuchMethod getValue() in Class: %s.", type.getName()));
-            }
-        } else {
-            this.method = TABLE_METHOD_OF_ENUM_TYPES.computeIfAbsent(type, k -> {
+        MetaClass metaClass = MetaClass.forClass(type, reflectorFactory);
+        String name = "value";
+        if (!IEnum.class.isAssignableFrom(type)) {
+            name = TABLE_METHOD_OF_ENUM_TYPES.computeIfAbsent(type.getName(), k -> {
                 Field field = dealEnumType(this.type).orElseThrow(() -> new IllegalArgumentException(String.format("Could not find @EnumValue in Class: %s.", type.getName())));
-                return ReflectionKit.getMethod(this.type, field);
+                return field.getName();
             });
         }
+        this.invoker = metaClass.getGetInvoker(name);
     }
-    
+
     @SuppressWarnings("Duplicates")
     @Override
     public void setNonNullParameter(PreparedStatement ps, int i, Enum<?> parameter, JdbcType jdbcType)
         throws SQLException {
-        try {
-            this.method.setAccessible(true);
-            if (jdbcType == null) {
-                ps.setObject(i, this.method.invoke(parameter));
-            } else {
-                // see r3589
-                ps.setObject(i, this.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, this.type.getName());
+        if (jdbcType == null) {
+            ps.setObject(i, this.getValue(parameter));
+        } else {
+            // see r3589
+            ps.setObject(i, this.getValue(parameter), jdbcType.TYPE_CODE);
         }
     }
 
@@ -96,7 +84,7 @@ public class MybatisEnumTypeHandler<E extends Enum<?>> extends BaseTypeHandler<E
         if (null == rs.getObject(columnName) && rs.wasNull()) {
             return null;
         }
-        return EnumUtils.valueOf(this.type, rs.getObject(columnName), this.method);
+        return this.valueOf(this.type, rs.getObject(columnName));
     }
 
     @Override
@@ -104,7 +92,7 @@ public class MybatisEnumTypeHandler<E extends Enum<?>> extends BaseTypeHandler<E
         if (null == rs.getObject(columnIndex) && rs.wasNull()) {
             return null;
         }
-        return EnumUtils.valueOf(this.type, rs.getObject(columnIndex), this.method);
+        return this.valueOf(this.type, rs.getObject(columnIndex));
     }
 
     @Override
@@ -112,10 +100,39 @@ public class MybatisEnumTypeHandler<E extends Enum<?>> extends BaseTypeHandler<E
         if (null == cs.getObject(columnIndex) && cs.wasNull()) {
             return null;
         }
-        return EnumUtils.valueOf(this.type, cs.getObject(columnIndex), this.method);
+        return this.valueOf(this.type, cs.getObject(columnIndex));
     }
 
     public static Optional<Field> dealEnumType(Class<?> clazz) {
         return clazz.isEnum() ? Arrays.stream(clazz.getDeclaredFields()).filter(field -> field.isAnnotationPresent(EnumValue.class)).findFirst() : Optional.empty();
     }
+
+    private <E extends Enum<?>> E valueOf(Class<E> enumClass, Object value) {
+        E[] es = enumClass.getEnumConstants();
+        return Arrays.stream(es).filter((e) -> equalsValue(value, getValue(e))).findAny().orElse(null);
+    }
+
+    /**
+     * 值比较
+     *
+     * @param sourceValue 数据库字段值
+     * @param targetValue 当前枚举属性值
+     * @return 是否匹配
+     * @since 3.2.1
+     */
+    protected boolean equalsValue(Object sourceValue, Object targetValue) {
+        if (sourceValue instanceof Number && targetValue instanceof Number
+            && new BigDecimal(String.valueOf(sourceValue)).compareTo(new BigDecimal(String.valueOf(targetValue))) == 0) {
+            return true;
+        }
+        return Objects.equals(sourceValue, targetValue);
+    }
+
+    private Object getValue(Object object) {
+        try {
+            return invoker.invoke(object, new Object[0]);
+        } catch (ReflectiveOperationException e) {
+            throw ExceptionUtils.mpe(e);
+        }
+    }
 }