浏览代码

枚举处理优化,不再需要'typeEnumsPackage'这个配置

miemie 3 年之前
父节点
当前提交
0a286e1195

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

@@ -200,10 +200,6 @@ public class MybatisPlusAutoConfiguration implements InitializingBean {
         }
         Optional.ofNullable(defaultLanguageDriver).ifPresent(factory::setDefaultScriptingLanguageDriver);
 
-        // TODO 自定义枚举包
-        if (StringUtils.hasLength(this.properties.getTypeEnumsPackage())) {
-            factory.setTypeEnumsPackage(this.properties.getTypeEnumsPackage());
-        }
         // TODO 此处必为非 NULL
         GlobalConfig globalConfig = this.properties.getGlobalConfig();
         // TODO 注入填充器

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

@@ -106,8 +106,11 @@ public class MybatisPlusProperties {
     private MybatisConfiguration configuration;
 
     /**
-     * TODO 枚举包扫描
+     * 不再需要这个配置,放心删除
+     *
+     * @deprecated 2022-03-07
      */
+    @Deprecated
     private String typeEnumsPackage;
 
     /**

+ 10 - 0
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/MybatisConfiguration.java

@@ -15,6 +15,7 @@
  */
 package com.baomidou.mybatisplus.core;
 
+import com.baomidou.mybatisplus.core.handlers.CompositeEnumTypeHandler;
 import com.baomidou.mybatisplus.core.mapper.Mapper;
 import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
 import com.baomidou.mybatisplus.core.toolkit.GlobalConfigUtils;
@@ -38,6 +39,7 @@ import org.apache.ibatis.session.Configuration;
 import org.apache.ibatis.session.ExecutorType;
 import org.apache.ibatis.session.SqlSession;
 import org.apache.ibatis.transaction.Transaction;
+import org.apache.ibatis.type.TypeHandler;
 
 import java.util.Collection;
 import java.util.HashMap;
@@ -88,6 +90,7 @@ public class MybatisConfiguration extends Configuration {
     public MybatisConfiguration() {
         super();
         this.mapUnderscoreToCamelCase = true;
+        typeHandlerRegistry.setDefaultEnumTypeHandler(CompositeEnumTypeHandler.class);
         languageRegistry.setDefaultDriverClass(MybatisXMLLanguageDriver.class);
     }
 
@@ -212,6 +215,13 @@ public class MybatisConfiguration extends Configuration {
         getLanguageRegistry().setDefaultDriverClass(driver);
     }
 
+    @Override
+    public void setDefaultEnumTypeHandler(Class<? extends TypeHandler> typeHandler) {
+        if (typeHandler != null) {
+            CompositeEnumTypeHandler.setDefaultEnumTypeHandler(typeHandler);
+        }
+    }
+
     @Override
     public void addKeyGenerator(String id, KeyGenerator keyGenerator) {
         keyGenerators.put(id, keyGenerator);

+ 79 - 0
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/handlers/CompositeEnumTypeHandler.java

@@ -0,0 +1,79 @@
+package com.baomidou.mybatisplus.core.handlers;
+
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
+import lombok.Setter;
+import org.apache.ibatis.type.EnumTypeHandler;
+import org.apache.ibatis.type.JdbcType;
+import org.apache.ibatis.type.TypeException;
+import org.apache.ibatis.type.TypeHandler;
+
+import java.lang.reflect.Constructor;
+import java.sql.CallableStatement;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * @author miemie
+ * @since 2022-03-07
+ */
+public class CompositeEnumTypeHandler<E extends Enum<E>> implements TypeHandler<E> {
+
+    private static final Map<Class<?>, Boolean> MP_ENUM_CACHE = new ConcurrentHashMap<>();
+    @Setter
+    private static Class<? extends TypeHandler> defaultEnumTypeHandler = EnumTypeHandler.class;
+    private final TypeHandler<E> delegate;
+
+    public CompositeEnumTypeHandler(Class<E> enumClassType) {
+        if (enumClassType == null) {
+            throw new IllegalArgumentException("Type argument cannot be null");
+        }
+        if (CollectionUtils.computeIfAbsent(MP_ENUM_CACHE, enumClassType, MybatisEnumTypeHandler::isMpEnums)) {
+            delegate = new MybatisEnumTypeHandler<>(enumClassType);
+        } else {
+            delegate = getInstance(enumClassType, defaultEnumTypeHandler);
+        }
+    }
+
+    @Override
+    public void setParameter(PreparedStatement ps, int i, E parameter, JdbcType jdbcType) throws SQLException {
+        delegate.setParameter(ps, i, parameter, jdbcType);
+    }
+
+    @Override
+    public E getResult(ResultSet rs, String columnName) throws SQLException {
+        return delegate.getResult(rs, columnName);
+    }
+
+    @Override
+    public E getResult(ResultSet rs, int columnIndex) throws SQLException {
+        return delegate.getResult(rs, columnIndex);
+    }
+
+    @Override
+    public E getResult(CallableStatement cs, int columnIndex) throws SQLException {
+        return delegate.getResult(cs, columnIndex);
+    }
+
+    @SuppressWarnings("unchecked")
+    public <T> TypeHandler<T> getInstance(Class<?> javaTypeClass, Class<?> typeHandlerClass) {
+        if (javaTypeClass != null) {
+            try {
+                Constructor<?> c = typeHandlerClass.getConstructor(Class.class);
+                return (TypeHandler<T>) c.newInstance(javaTypeClass);
+            } catch (NoSuchMethodException ignored) {
+                // ignored
+            } catch (Exception e) {
+                throw new TypeException("Failed invoking constructor for handler " + typeHandlerClass, e);
+            }
+        }
+        try {
+            Constructor<?> c = typeHandlerClass.getConstructor();
+            return (TypeHandler<T>) c.newInstance();
+        } catch (Exception e) {
+            throw new TypeException("Unable to find a usable constructor for " + typeHandlerClass, e);
+        }
+    }
+}

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

@@ -20,11 +20,7 @@ import com.baomidou.mybatisplus.core.MybatisPlusVersion;
 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.toolkit.SqlHelper;
 import com.baomidou.mybatisplus.extension.toolkit.SqlRunner;
 import lombok.Setter;
@@ -43,7 +39,6 @@ import org.apache.ibatis.session.Configuration;
 import org.apache.ibatis.session.SqlSessionFactory;
 import org.apache.ibatis.transaction.TransactionFactory;
 import org.apache.ibatis.type.TypeHandler;
-import org.apache.ibatis.type.TypeHandlerRegistry;
 import org.mybatis.logging.Logger;
 import org.mybatis.logging.LoggerFactory;
 import org.mybatis.spring.SqlSessionFactoryBean;
@@ -141,9 +136,12 @@ public class MybatisSqlSessionFactoryBean implements FactoryBean<SqlSessionFacto
     private ObjectWrapperFactory objectWrapperFactory;
 
     /**
-     * TODO 自定义枚举包
+     * 不再需要这个配置,放心删除
+     *
+     * @deprecated 2022-03-07
      */
     @Setter
+    @Deprecated
     private String typeEnumsPackage;
 
     // TODO 自定义全局配置
@@ -569,39 +567,6 @@ public class MybatisSqlSessionFactoryBean implements FactoryBean<SqlSessionFacto
         } else {
             LOGGER.debug(() -> "Property 'mapperLocations' was not specified.");
         }
-        //延迟处理,如果需要注册,必须放置在mapper文件处理解析后.
-        if (hasLength(this.typeEnumsPackage)) {
-            Set<Class<?>> classes;
-            if (typeEnumsPackage.contains(StringPool.STAR) && !typeEnumsPackage.contains(StringPool.COMMA)
-                && !typeEnumsPackage.contains(StringPool.SEMICOLON)) {
-                classes = scanClasses(typeEnumsPackage, null);
-                if (classes.isEmpty()) {
-                    LOGGER.warn(() -> "Can't find class in '[" + typeEnumsPackage + "]' package. Please check your configuration.");
-                }
-            } else {
-                classes = new HashSet<>();
-                String[] typeEnumsPackageArray = tokenizeToStringArray(this.typeEnumsPackage,
-                    ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
-                Assert.notNull(typeEnumsPackageArray, "not find typeEnumsPackage:" + typeEnumsPackage);
-                Stream.of(typeEnumsPackageArray).forEach(typePackage -> {
-                    try {
-                        Set<Class<?>> scanTypePackage = scanClasses(typePackage, null);
-                        if (scanTypePackage.isEmpty()) {
-                            LOGGER.warn(() -> "Can't find class in '[" + typePackage + "]' package. Please check your configuration.");
-                        } else {
-                            classes.addAll(scanTypePackage);
-                        }
-                    } catch (IOException e) {
-                        throw new MybatisPlusException("Cannot scan class in '[" + typePackage + "]' package", e);
-                    }
-                });
-            }
-            TypeHandlerRegistry typeHandlerRegistry = targetConfiguration.getTypeHandlerRegistry();
-            classes.stream()
-                .filter(Class::isEnum)
-                .filter(MybatisEnumTypeHandler::isMpEnums)
-                .forEach(cls -> typeHandlerRegistry.register(cls, MybatisEnumTypeHandler.class));
-        }
 
         final SqlSessionFactory sqlSessionFactory = new MybatisSqlSessionFactoryBuilder().build(targetConfiguration);
 

+ 3 - 4
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/enums/Entity.java

@@ -1,10 +1,8 @@
 package com.baomidou.mybatisplus.test.enums;
 
-import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableName;
 import lombok.Data;
 import lombok.experimental.Accessors;
-import org.apache.ibatis.type.EnumOrdinalTypeHandler;
 
 import java.io.Serializable;
 
@@ -23,7 +21,8 @@ public class Entity implements Serializable {
     private EnumStr enumStr;
 
     private EnumInt enumInt;
-
-    @TableField(typeHandler = EnumOrdinalTypeHandler.class, javaType = true)
+    /**
+     * 使用 EnumOrdinalTypeHandler
+     */
     private EnumOrdinal enumOrdinal;
 }

+ 5 - 2
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/enums/EnumTest.java

@@ -1,8 +1,8 @@
 package com.baomidou.mybatisplus.test.enums;
 
-import com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler;
 import com.baomidou.mybatisplus.test.BaseDbTest;
 import org.apache.ibatis.session.Configuration;
+import org.apache.ibatis.type.EnumOrdinalTypeHandler;
 import org.junit.jupiter.api.Test;
 
 import java.util.Arrays;
@@ -47,7 +47,10 @@ class EnumTest extends BaseDbTest<EntityMapper> {
 
     @Override
     protected Consumer<Configuration> consumer() {
-        return i -> i.setDefaultEnumTypeHandler(MybatisEnumTypeHandler.class);
+        /**
+         * see {@link Entity#enumOrdinal}
+         */
+        return i -> i.setDefaultEnumTypeHandler(EnumOrdinalTypeHandler.class);
     }
 
     @Override

+ 0 - 1
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/config/MybatisPlusConfig.java

@@ -88,7 +88,6 @@ public class MybatisPlusConfig {
             }
         });
         sqlSessionFactory.setGlobalConfig(globalConfig);
-        sqlSessionFactory.setTypeEnumsPackage("com.baomidou.mybatisplus.test.h2.enums");
         return sqlSessionFactory.getObject();
     }