miemie 5 роки тому
батько
коміт
7f8a365dcb

+ 3 - 0
mybatis-plus-boot-starter/src/main/java/com/baomidou/mybatisplus/autoconfigure/MybatisPlusProperties.java

@@ -107,7 +107,10 @@ public class MybatisPlusProperties {
 
     /**
      * TODO 枚举包扫描
+     *
+     * @deprecated 3.3.3 @2020-06-23 初始化entity时会自动把符合条件的枚举处理了
      */
+    @Deprecated
     private String typeEnumsPackage;
 
     /**

+ 176 - 0
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/handlers/MybatisEnumTypeHandler.java

@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2011-2020, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.core.handlers;
+
+import com.baomidou.mybatisplus.annotation.EnumValue;
+import com.baomidou.mybatisplus.core.enums.IEnum;
+import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils;
+import org.apache.ibatis.reflection.DefaultReflectorFactory;
+import org.apache.ibatis.reflection.MetaClass;
+import org.apache.ibatis.reflection.ReflectorFactory;
+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.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;
+
+/**
+ * 自定义枚举属性转换器
+ *
+ * @author hubin
+ * @since 2017-10-11
+ */
+public class MybatisEnumTypeHandler<E extends Enum<?>> extends BaseTypeHandler<Enum<?>> {
+
+    private static final Map<String, String> TABLE_METHOD_OF_ENUM_TYPES = new ConcurrentHashMap<>();
+    private static ReflectorFactory reflectorFactory = new DefaultReflectorFactory();
+    private final Class<E> type;
+
+    private Invoker invoker;
+
+    public MybatisEnumTypeHandler(Class<E> type) {
+        if (type == null) {
+            throw new IllegalArgumentException("Type argument cannot be null");
+        }
+        this.type = type;
+        MetaClass metaClass = MetaClass.forClass(type, reflectorFactory);
+        String name = "value";
+        if (!IEnum.class.isAssignableFrom(type)) {
+            name = findEnumValueFieldName(this.type).orElseThrow(() -> new IllegalArgumentException(String.format("Could not find @EnumValue in Class: %s.", this.type.getName())));
+        }
+        this.invoker = metaClass.getGetInvoker(name);
+    }
+
+    /**
+     * 查找标记EnumValue字段
+     *
+     * @param clazz class
+     * @return EnumValue字段
+     * @deprecated 3.3.1 {@link #findEnumValueFieldName(Class)}
+     */
+    @Deprecated
+    public static Optional<Field> dealEnumType(Class<?> clazz) {
+        return clazz.isEnum() ? Arrays.stream(clazz.getDeclaredFields()).filter(field -> field.isAnnotationPresent(EnumValue.class)).findFirst() : Optional.empty();
+    }
+
+    /**
+     * 查找标记标记EnumValue字段
+     *
+     * @param clazz class
+     * @return EnumValue字段
+     * @since 3.3.1
+     */
+    public static Optional<String> findEnumValueFieldName(Class<?> clazz) {
+        if (clazz != null && clazz.isEnum()) {
+            String className = clazz.getName();
+            return Optional.ofNullable(TABLE_METHOD_OF_ENUM_TYPES.computeIfAbsent(className, key -> {
+                Optional<Field> optional = Arrays.stream(clazz.getDeclaredFields())
+                    .filter(field -> field.isAnnotationPresent(EnumValue.class))
+                    .findFirst();
+                return optional.map(Field::getName).orElse(null);
+            }));
+        }
+        return Optional.empty();
+    }
+
+    /**
+     * 判断是否为MP枚举处理
+     *
+     * @param clazz class
+     * @return 是否为MP枚举处理
+     * @since 3.3.1
+     */
+    public static boolean isMpEnums(Class<?> clazz) {
+        return clazz != null && clazz.isEnum() && (IEnum.class.isAssignableFrom(clazz) || findEnumValueFieldName(clazz).isPresent());
+    }
+
+    @SuppressWarnings("Duplicates")
+    @Override
+    public void setNonNullParameter(PreparedStatement ps, int i, Enum<?> parameter, JdbcType jdbcType)
+        throws SQLException {
+        if (jdbcType == null) {
+            ps.setObject(i, this.getValue(parameter));
+        } else {
+            // see r3589
+            ps.setObject(i, this.getValue(parameter), jdbcType.TYPE_CODE);
+        }
+    }
+
+    @Override
+    public E getNullableResult(ResultSet rs, String columnName) throws SQLException {
+        if (null == rs.getObject(columnName) && rs.wasNull()) {
+            return null;
+        }
+        return this.valueOf(this.type, rs.getObject(columnName));
+    }
+
+    @Override
+    public E getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
+        if (null == rs.getObject(columnIndex) && rs.wasNull()) {
+            return null;
+        }
+        return this.valueOf(this.type, rs.getObject(columnIndex));
+    }
+
+    @Override
+    public E getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
+        if (null == cs.getObject(columnIndex) && cs.wasNull()) {
+            return null;
+        }
+        return this.valueOf(this.type, cs.getObject(columnIndex));
+    }
+
+    private 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.3.0
+     */
+    protected boolean equalsValue(Object sourceValue, Object targetValue) {
+        String sValue = Objects.toString(sourceValue).trim();
+        String tValue = Objects.toString(targetValue).trim();
+        if (sourceValue instanceof Number && targetValue instanceof Number
+            && new BigDecimal(sValue).compareTo(new BigDecimal(tValue)) == 0) {
+            return true;
+        }
+        return Objects.equals(sValue, tValue);
+    }
+
+    private Object getValue(Object object) {
+        try {
+            return invoker.invoke(object, new Object[0]);
+        } catch (ReflectiveOperationException e) {
+            throw ExceptionUtils.mpe(e);
+        }
+    }
+}

+ 18 - 3
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/metadata/TableFieldInfo.java

@@ -16,14 +16,15 @@
 package com.baomidou.mybatisplus.core.metadata;
 
 import com.baomidou.mybatisplus.annotation.*;
-import com.baomidou.mybatisplus.core.MybatisConfiguration;
 import com.baomidou.mybatisplus.core.config.GlobalConfig;
+import com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler;
 import com.baomidou.mybatisplus.core.toolkit.Constants;
 import com.baomidou.mybatisplus.core.toolkit.StringUtils;
 import com.baomidou.mybatisplus.core.toolkit.sql.SqlScriptUtils;
 import lombok.*;
 import org.apache.ibatis.mapping.ResultMapping;
 import org.apache.ibatis.reflection.Reflector;
+import org.apache.ibatis.session.Configuration;
 import org.apache.ibatis.type.JdbcType;
 import org.apache.ibatis.type.TypeHandler;
 import org.apache.ibatis.type.TypeHandlerRegistry;
@@ -157,13 +158,20 @@ public class TableFieldInfo implements Constants {
     /**
      * 全新的 存在 TableField 注解时使用的构造函数
      */
-    @SuppressWarnings("unchecked")
+    @SuppressWarnings({"unchecked", "rawtypes"})
     public TableFieldInfo(GlobalConfig.DbConfig dbConfig, TableInfo tableInfo, Field field, TableField tableField,
                           Reflector reflector) {
         field.setAccessible(true);
         this.field = field;
         this.version = field.getAnnotation(Version.class) != null;
         this.property = field.getName();
+        Class<?> fieldType = field.getType();
+        if (fieldType.isEnum() && MybatisEnumTypeHandler.isMpEnums(fieldType)) {
+            TypeHandlerRegistry registry = tableInfo.getConfiguration().getTypeHandlerRegistry();
+            if (registry.getTypeHandler(fieldType) == null) {
+                registry.register(fieldType, MybatisEnumTypeHandler.class);
+            }
+        }
         this.propertyType = reflector.getGetterType(this.property);
         this.isPrimitive = this.propertyType.isPrimitive();
         this.isCharSequence = StringUtils.isCharSequence(this.propertyType);
@@ -247,6 +255,13 @@ public class TableFieldInfo implements Constants {
         this.field = field;
         this.version = field.getAnnotation(Version.class) != null;
         this.property = field.getName();
+        Class<?> fieldType = field.getType();
+        if (fieldType.isEnum() && MybatisEnumTypeHandler.isMpEnums(fieldType)) {
+            TypeHandlerRegistry registry = tableInfo.getConfiguration().getTypeHandlerRegistry();
+            if (registry.getTypeHandler(fieldType) == null) {
+                registry.register(fieldType, MybatisEnumTypeHandler.class);
+            }
+        }
         this.propertyType = reflector.getGetterType(this.property);
         this.isPrimitive = this.propertyType.isPrimitive();
         this.isCharSequence = StringUtils.isCharSequence(this.propertyType);
@@ -445,7 +460,7 @@ public class TableFieldInfo implements Constants {
      * @param configuration MybatisConfiguration
      * @return ResultMapping
      */
-    ResultMapping getResultMapping(final MybatisConfiguration configuration) {
+    ResultMapping getResultMapping(final Configuration configuration) {
         ResultMapping.Builder builder = new ResultMapping.Builder(configuration, property,
             StringUtils.getTargetColumn(column), propertyType);
         TypeHandlerRegistry registry = configuration.getTypeHandlerRegistry();

+ 2 - 3
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/metadata/TableInfo.java

@@ -17,7 +17,6 @@ package com.baomidou.mybatisplus.core.metadata;
 
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.KeySequence;
-import com.baomidou.mybatisplus.core.MybatisConfiguration;
 import com.baomidou.mybatisplus.core.toolkit.*;
 import com.baomidou.mybatisplus.core.toolkit.sql.SqlScriptUtils;
 import lombok.AccessLevel;
@@ -102,7 +101,7 @@ public class TableInfo implements Constants {
      * MybatisConfiguration 标记 (Configuration内存地址值)
      */
     @Getter
-    private MybatisConfiguration configuration;
+    private Configuration configuration;
     /**
      * 是否开启逻辑删除
      */
@@ -178,7 +177,7 @@ public class TableInfo implements Constants {
      */
     void setConfiguration(Configuration configuration) {
         Assert.notNull(configuration, "Error: You need Initialize MybatisConfiguration !");
-        this.configuration = (MybatisConfiguration) configuration;
+        this.configuration = configuration;
         this.underCamel = configuration.isMapUnderscoreToCamelCase();
     }
 

+ 2 - 0
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/handlers/MybatisEnumTypeHandler.java

@@ -42,7 +42,9 @@ import java.util.concurrent.ConcurrentHashMap;
  *
  * @author hubin
  * @since 2017-10-11
+ * @deprecated 3.3.3 @2020-06-23 use {@link com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler}
  */
+@Deprecated
 public class MybatisEnumTypeHandler<E extends Enum<?>> extends BaseTypeHandler<Enum<?>> {
 
     private static ReflectorFactory reflectorFactory = new DefaultReflectorFactory();

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

@@ -21,10 +21,10 @@ import com.baomidou.mybatisplus.core.MybatisSqlSessionFactoryBuilder;
 import com.baomidou.mybatisplus.core.MybatisXMLConfigBuilder;
 import com.baomidou.mybatisplus.core.config.GlobalConfig;
 import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
+import com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler;
 import com.baomidou.mybatisplus.core.toolkit.Assert;
 import com.baomidou.mybatisplus.core.toolkit.GlobalConfigUtils;
 import com.baomidou.mybatisplus.core.toolkit.StringPool;
-import com.baomidou.mybatisplus.extension.handlers.MybatisEnumTypeHandler;
 import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
 import lombok.Setter;
 import org.apache.ibatis.builder.xml.XMLMapperBuilder;
@@ -139,8 +139,13 @@ public class MybatisSqlSessionFactoryBean implements FactoryBean<SqlSessionFacto
 
     private ObjectWrapperFactory objectWrapperFactory;
 
-    // TODO 自定义枚举包
+    /**
+     * TODO 自定义枚举包
+     *
+     * @deprecated 3.3.3 @2020-06-23 初始化entity时会自动把符合条件的枚举处理了
+     */
     @Setter
+    @Deprecated
     private String typeEnumsPackage;
 
     // TODO 自定义全局配置