소스 검색

重新撸一版主键生成器.

聂秋秋 5 년 전
부모
커밋
e6be9075cf

+ 3 - 4
mybatis-plus-annotation/src/main/java/com/baomidou/mybatisplus/annotation/IdType.java

@@ -41,14 +41,13 @@ public enum IdType {
 
     /* 以下3种类型、只有当插入对象ID 为空,才自动填充。 */
     /**
-     * 分配ID (主键类型为 number 对应 #{@link com.baomidou.mybatisplus.core.incrementer.IdGenerator#nextId}) </p>
-     * 否则认为是 string 类型 对上值进行 toString
+     * 分配ID (主键类型为number或string)
      *
      * @since 3.3.0
      */
     ASSIGN_ID(3),
     /**
-     * 分配UUID (主键类型为 string 对应 #{@link com.baomidou.mybatisplus.core.incrementer.IdGenerator#nextUUID})
+     * 分配UUID (主键类型为 string)
      *
      * @since 3.3.0
      */
@@ -69,7 +68,7 @@ public enum IdType {
      * @deprecated 3.3.0 please use {@link #ASSIGN_ID}
      */
     @Deprecated
-    ID_WORKER_STR(5);
+    ID_WORKER_STR(3);
 
     private final int key;
 

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

@@ -19,9 +19,7 @@ package com.baomidou.mybatisplus.autoconfigure;
 import com.baomidou.mybatisplus.core.MybatisConfiguration;
 import com.baomidou.mybatisplus.core.config.GlobalConfig;
 import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
-import com.baomidou.mybatisplus.core.incrementer.DefaultGenerator;
 import com.baomidou.mybatisplus.core.incrementer.IKeyGenerator;
-import com.baomidou.mybatisplus.core.incrementer.IdGenerator;
 import com.baomidou.mybatisplus.core.injector.ISqlInjector;
 import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
 import org.apache.ibatis.annotations.Mapper;
@@ -219,8 +217,6 @@ public class MybatisPlusAutoConfiguration implements InitializingBean {
             ISqlInjector iSqlInjector = this.applicationContext.getBean(ISqlInjector.class);
             globalConfig.setSqlInjector(iSqlInjector);
         }
-        IdGenerator idGenerator = this.applicationContext.getBean(IdGenerator.class);
-        globalConfig.setIdGenerator(idGenerator);
         // TODO 设置 GlobalConfig 到 MybatisSqlSessionFactoryBean
         factory.setGlobalConfig(globalConfig);
         return factory.getObject();
@@ -252,15 +248,6 @@ public class MybatisPlusAutoConfiguration implements InitializingBean {
         }
     }
 
-    @Bean
-    @ConditionalOnMissingBean
-    public IdGenerator idGenerator() {
-        GlobalConfig globalConfig = this.properties.getGlobalConfig();
-        if (globalConfig.getWorkerId() != null && globalConfig.getDatacenterId() != null) {
-            return new DefaultGenerator(globalConfig.getWorkerId(), globalConfig.getDatacenterId());
-        }
-        return new DefaultGenerator();
-    }
 
     /**
      * This will just scan the same base package as Spring Boot does. If you want more power, you can explicitly use

+ 6 - 11
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/MybatisDefaultParameterHandler.java

@@ -162,20 +162,15 @@ public class MybatisDefaultParameterHandler extends DefaultParameterHandler {
         // 填充主键
         if (!StringUtils.isBlank(tableInfo.getKeyProperty())
             && null != tableInfo.getIdType() && tableInfo.getIdType().getKey() >= 3) {
-            IdGenerator idGenerator = GlobalConfigUtils.getGlobalConfig(tableInfo.getConfiguration()).getIdGenerator();
+            IdGenerator idGenerator = GlobalConfigUtils.getGlobalConfig(tableInfo.getConfiguration()).getIdGenerator(tableInfo.getIdType());
             Object idValue = metaObject.getValue(tableInfo.getKeyProperty());
             /* 自定义 ID */
             if (StringUtils.checkValNull(idValue)) {
-                if (tableInfo.getIdType() == IdType.ASSIGN_ID || tableInfo.getIdType() == IdType.ID_WORKER) {
-                    if (Number.class.isAssignableFrom(tableInfo.getKeyType())) {
-                        metaObject.setValue(tableInfo.getKeyProperty(), idGenerator.nextId(parameterObject));
-                    } else {
-                        metaObject.setValue(tableInfo.getKeyProperty(), idGenerator.nextId(parameterObject).toString());
-                    }
-                } else if (tableInfo.getIdType() == IdType.ID_WORKER_STR) {
-                    metaObject.setValue(tableInfo.getKeyProperty(), idGenerator.nextId(parameterObject).toString());
-                } else if (tableInfo.getIdType() == IdType.ASSIGN_UUID || tableInfo.getIdType() == IdType.UUID) {
-                    metaObject.setValue(tableInfo.getKeyProperty(), idGenerator.nextUUID(parameterObject));
+                // 应该只有数值型和字符串的区别了.
+                if (Number.class.isAssignableFrom(tableInfo.getKeyType())) {
+                    metaObject.setValue(tableInfo.getKeyProperty(), idGenerator.generate(parameterObject));
+                } else {
+                    metaObject.setValue(tableInfo.getKeyProperty(), idGenerator.generate(parameterObject).toString());
                 }
             }
         }

+ 7 - 11
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/MybatisSqlSessionFactoryBuilder.java

@@ -15,9 +15,10 @@
  */
 package com.baomidou.mybatisplus.core;
 
+import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.core.config.GlobalConfig;
-import com.baomidou.mybatisplus.core.incrementer.DefaultGenerator;
 import com.baomidou.mybatisplus.core.incrementer.IdGenerator;
+import com.baomidou.mybatisplus.core.incrementer.SnowflakeGenerator;
 import com.baomidou.mybatisplus.core.injector.SqlRunnerInjector;
 import com.baomidou.mybatisplus.core.toolkit.IdWorker;
 import org.apache.ibatis.exceptions.ExceptionFactory;
@@ -81,17 +82,12 @@ public class MybatisSqlSessionFactoryBuilder extends SqlSessionFactoryBuilder {
     public SqlSessionFactory build(Configuration config) {
         MybatisConfiguration configuration = (MybatisConfiguration) config;
         GlobalConfig globalConfig = configuration.getGlobalConfig();
-        IdGenerator idGenerator = globalConfig.getIdGenerator();
-        if (globalConfig.getIdGenerator() == null) {
-            if (null != globalConfig.getWorkerId() && null != globalConfig.getDatacenterId()) {
-                idGenerator = new DefaultGenerator(globalConfig.getWorkerId(), globalConfig.getDatacenterId());
-            } else {
-                idGenerator = new DefaultGenerator();
-            }
-            globalConfig.setIdGenerator(idGenerator);
+        if (null != globalConfig.getWorkerId() && null != globalConfig.getDatacenterId()) {
+            IdGenerator idGenerator = new SnowflakeGenerator(globalConfig.getWorkerId(), globalConfig.getDatacenterId());
+            globalConfig.registerIdGenerator(IdType.ASSIGN_ID, idGenerator);
+            //TODO 这里只是为了兼容下,并没多大重要,方法标记过时了.
+            IdWorker.setIdGenerator(idGenerator);
         }
-        //TODO 这里只是为了兼容下,并没多大重要,方法标记过时了.
-        IdWorker.setIdGenerator(idGenerator);
         if (globalConfig.isEnableSqlRunner()) {
             new SqlRunnerInjector().inject(configuration);
         }

+ 39 - 5
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/config/GlobalConfig.java

@@ -20,17 +20,23 @@ import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
 import com.baomidou.mybatisplus.core.incrementer.IKeyGenerator;
 import com.baomidou.mybatisplus.core.incrementer.IdGenerator;
+import com.baomidou.mybatisplus.core.incrementer.SnowflakeGenerator;
+import com.baomidou.mybatisplus.core.incrementer.UUIDGenerator;
 import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
 import com.baomidou.mybatisplus.core.injector.ISqlInjector;
 import com.baomidou.mybatisplus.core.mapper.Mapper;
 import lombok.AccessLevel;
 import lombok.Data;
+import lombok.Getter;
 import lombok.Setter;
 import lombok.experimental.Accessors;
 import org.apache.ibatis.session.SqlSessionFactory;
 
 import java.io.Serializable;
+import java.util.Collections;
+import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentSkipListSet;
 
 /**
@@ -44,6 +50,16 @@ import java.util.concurrent.ConcurrentSkipListSet;
 @SuppressWarnings("serial")
 public class GlobalConfig implements Serializable {
 
+    /**
+     * 默认提供的主键生成器
+     */
+    private static Map<String, IdGenerator> defaultIdGeneratorMap = new ConcurrentHashMap<>();
+
+    static {
+        defaultIdGeneratorMap.put(String.valueOf(IdType.ASSIGN_UUID.getKey()),new UUIDGenerator());
+        defaultIdGeneratorMap.put(String.valueOf(IdType.ASSIGN_ID.getKey()),new SnowflakeGenerator());
+    }
+
     /**
      * 是否开启 LOGO
      */
@@ -51,16 +67,16 @@ public class GlobalConfig implements Serializable {
     /**
      * 机器 ID 部分
      *
-     * @see #setIdGenerator(IdGenerator)
-     * @deprecated 3.2.1 建议手动初始化,Spring应用直接@bean注入SnowflakeIdGenerator即可.
+     * @see #registerIdGenerator(IdType, IdGenerator)
+     * @deprecated 3.3.0
      */
     @Deprecated
     private Long workerId;
     /**
      * 数据标识 ID 部分
      *
-     * @see #setIdGenerator(IdGenerator)
-     * @deprecated 3.2.1 建议手动初始化,Spring应用直接@bean注入SnowflakeIdGenerator即可.
+     * @see #registerIdGenerator(IdType, IdGenerator)
+     * @deprecated 3.3.0
      */
     @Deprecated
     private Long datacenterId;
@@ -96,7 +112,25 @@ public class GlobalConfig implements Serializable {
     /**
      * 主键生成器
      */
-    private IdGenerator idGenerator;
+    @Setter(value = AccessLevel.NONE)
+    @Getter(value = AccessLevel.NONE)
+    private Map<String, IdGenerator> idGeneratorMap = new ConcurrentHashMap<>(defaultIdGeneratorMap);
+
+    /**
+     * 注册ID生成器
+     *
+     * @param idType      idType 暂时不开放string注册
+     * @param idGenerator 生成器
+     */
+    public GlobalConfig registerIdGenerator(IdType idType, IdGenerator idGenerator) {
+        idGeneratorMap.put(String.valueOf(idType.getKey()), idGenerator);
+        return this;
+    }
+
+    public IdGenerator getIdGenerator(IdType idType) {
+        return Collections.unmodifiableMap(idGeneratorMap).get(String.valueOf(idType.getKey()));
+    }
+
     /**
      * 标记全局设置 (统一所有入口)
      */

+ 6 - 15
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/incrementer/IdGenerator.java

@@ -15,33 +15,24 @@
  */
 package com.baomidou.mybatisplus.core.incrementer;
 
-import com.baomidou.mybatisplus.annotation.IdType;
-import com.baomidou.mybatisplus.core.toolkit.IdWorker;
+
+import java.io.Serializable;
 
 /**
  * Id生成器接口
  *
- * @author sd-wangtaicheng@sdcncsi.com.cn qiuqiu
+ * @author sd-wangtaicheng@sdcncsi.com.cn nieqiuqiu
  * @since 2019-10-15
- * @since 3.2.1
+ * @since 3.3.0
  */
 public interface IdGenerator {
 
     /**
-     * 生成Id {@link IdType#ID_WORKER}
+     * 生成Id
      *
      * @param entity 实体
      * @return id
      */
-    Number nextId(Object entity);
+    Serializable generate(Object entity);
 
-    /**
-     * 获取uuid {@link IdType#UUID}
-     *
-     * @param entity 实体
-     * @return uuid
-     */
-    default String nextUUID(Object entity) {
-        return IdWorker.get32UUID();
-    }
 }

+ 9 - 8
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/incrementer/DefaultGenerator.java → mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/incrementer/SnowflakeGenerator.java

@@ -18,29 +18,30 @@ package com.baomidou.mybatisplus.core.incrementer;
 import com.baomidou.mybatisplus.core.toolkit.Sequence;
 
 /**
- * 默认ID生成器
+ * 雪花Id生成器
  *
- * @author sd-wangtaicheng@sdcncsi.com.cn
- * @date 2019/10/15
+ * @author sd-wangtaicheng@sdcncsi.com.cn nieqiuqiu
+ * @date 2019-10-15
+ * @since 3.3.0
  */
-public class DefaultGenerator implements IdGenerator {
+public class SnowflakeGenerator implements IdGenerator {
 
     private final Sequence sequence;
 
-    public DefaultGenerator() {
+    public SnowflakeGenerator() {
         this.sequence = new Sequence();
     }
 
-    public DefaultGenerator(long workerId, long dataCenterId) {
+    public SnowflakeGenerator(long workerId, long dataCenterId) {
         this.sequence = new Sequence(workerId, dataCenterId);
     }
 
-    public DefaultGenerator(Sequence sequence) {
+    public SnowflakeGenerator(Sequence sequence) {
         this.sequence = sequence;
     }
 
     @Override
-    public Long nextId(Object entity) {
+    public Long generate(Object entity) {
         return sequence.nextId();
     }
 }

+ 34 - 0
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/incrementer/UUIDGenerator.java

@@ -0,0 +1,34 @@
+/*
+ * 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.incrementer;
+
+
+import com.baomidou.mybatisplus.core.toolkit.IdWorker;
+
+/**
+ * UUID生成
+ *
+ * @author nieqiuqiu 2019-11-29
+ * @since 3.3.0
+ */
+public class UUIDGenerator implements IdGenerator {
+
+    @Override
+    public String generate(Object entity) {
+        return IdWorker.get32UUID();
+    }
+
+}

+ 15 - 12
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/IdWorker.java

@@ -15,8 +15,9 @@
  */
 package com.baomidou.mybatisplus.core.toolkit;
 
+import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.core.config.GlobalConfig;
-import com.baomidou.mybatisplus.core.incrementer.DefaultGenerator;
+import com.baomidou.mybatisplus.core.incrementer.SnowflakeGenerator;
 import com.baomidou.mybatisplus.core.incrementer.IdGenerator;
 
 import java.time.LocalDateTime;
@@ -35,10 +36,11 @@ public class IdWorker {
 
     /**
      * 主机和进程的机器码
-     * @deprecated 3.2.1
+     *
+     * @deprecated 3.3.0
      */
     @Deprecated
-    private static IdGenerator ID_GENERATOR = new DefaultGenerator();
+    private static IdGenerator ID_GENERATOR = new SnowflakeGenerator();
 
     /**
      * 毫秒格式化时间
@@ -49,22 +51,22 @@ public class IdWorker {
      * 获取唯一ID
      *
      * @return id
-     * @deprecated 3.2.1 spring应用可以通过@IdGenerator,非spring应用请自行控制IdGenerator的实例化
+     * @deprecated 3.3.0
      */
     @Deprecated
     public static long getId() {
-        return Long.parseLong(ID_GENERATOR.nextId(new Object()).toString());
+        return Long.parseLong(ID_GENERATOR.generate(new Object()).toString());
     }
 
     /**
      * 获取唯一ID
      *
      * @return id
-     * @deprecated 3.2.1 spring应用可以通过@IdGenerator,非spring应用请自行控制IdGenerator的实例化
+     * @deprecated 3.3.0
      */
     @Deprecated
     public static String getIdStr() {
-        return String.valueOf(ID_GENERATOR.nextId(new Object()));
+        return String.valueOf(ID_GENERATOR.generate(new Object()));
     }
 
     /**
@@ -77,7 +79,8 @@ public class IdWorker {
     /**
      * 时间 ID = Time + ID
      * <p>例如:可用于商品订单 ID</p>
-     * @deprecated 3.2.1  spring应用可以通过@IdGenerator,非spring应用请自行控制IdGenerator的实例化
+     *
+     * @deprecated 3.3.0
      */
     @Deprecated
     public static String getTimeId() {
@@ -90,19 +93,19 @@ public class IdWorker {
      * @param workerId     工作机器 ID
      * @param dataCenterId 序列号
      * @see #setIdGenerator(IdGenerator)
-     * @deprecated 3.2.1
+     * @deprecated 3.3.0
      */
     @Deprecated
     public static void initSequence(long workerId, long dataCenterId) {
-        ID_GENERATOR = new DefaultGenerator(workerId, dataCenterId);
+        ID_GENERATOR = new SnowflakeGenerator(workerId, dataCenterId);
     }
 
     /**
      * 自定义id 生成方式
      *
      * @param idGenerator id 生成器
-     * @see GlobalConfig#setIdGenerator(IdGenerator)
-     * @deprecated 3.2.1
+     * @see GlobalConfig#registerIdGenerator(IdType, IdGenerator)
+     * @deprecated 3.3.0
      */
     @Deprecated
     public static void setIdGenerator(IdGenerator idGenerator) {

+ 2 - 2
mybatis-plus-core/src/test/java/com/baomidou/mybatisplus/core/MybatisDefaultParameterHandlerTest.java

@@ -5,7 +5,7 @@ import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
-import com.baomidou.mybatisplus.core.incrementer.DefaultGenerator;
+import com.baomidou.mybatisplus.core.incrementer.SnowflakeGenerator;
 import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
 import com.baomidou.mybatisplus.core.toolkit.GlobalConfigUtils;
 import lombok.AllArgsConstructor;
@@ -51,7 +51,7 @@ class MybatisDefaultParameterHandlerTest {
         MappedStatement mappedStatement;
         Configuration configuration = new MybatisConfiguration();
         StaticSqlSource staticSqlSource = new StaticSqlSource(configuration, " ***********");
-        GlobalConfigUtils.getGlobalConfig(configuration).setIdGenerator(new DefaultGenerator()).setMetaObjectHandler(new MetaObjectHandler() {
+        GlobalConfigUtils.getGlobalConfig(configuration).registerIdGenerator(IdType.ASSIGN_ID,new SnowflakeGenerator()).setMetaObjectHandler(new MetaObjectHandler() {
 
             @Override
             public boolean compatibleFillId() {

+ 1 - 13
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/idgenerator/CustomIdGenerator.java

@@ -3,24 +3,12 @@ package com.baomidou.mybatisplus.test.h2.idgenerator;
 import com.baomidou.mybatisplus.core.incrementer.IdGenerator;
 import com.baomidou.mybatisplus.core.metadata.TableInfo;
 import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
-import com.baomidou.mybatisplus.core.toolkit.IdWorker;
 import org.apache.ibatis.reflection.SystemMetaObject;
 
 public class CustomIdGenerator implements IdGenerator {
 
     @Override
-    public String nextUUID(Object entity) {
-        String name = (String) SystemMetaObject.forObject(entity).getValue("name");
-        if ("旺仔".equals(name)) {
-            return "66666666666";
-        } else if ("靓仔".equals(name)) {
-            return "77777777777";
-        }
-        return IdWorker.get32UUID();
-    }
-
-    @Override
-    public Number nextId(Object entity) {
+    public Number generate(Object entity) {
         //可以将当前传入的class全类名来作为bizKey,或者提取参数来生成bizKey进行分布式Id调用生成.
         String bizKey = entity.getClass().getName();
         TableInfo tableInfo = TableInfoHelper.getTableInfo(entity.getClass());

+ 21 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/idgenerator/CustomUUIDGenerator.java

@@ -0,0 +1,21 @@
+package com.baomidou.mybatisplus.test.h2.idgenerator;
+
+import com.baomidou.mybatisplus.core.incrementer.IdGenerator;
+import com.baomidou.mybatisplus.core.toolkit.IdWorker;
+import org.apache.ibatis.reflection.SystemMetaObject;
+
+import java.io.Serializable;
+
+public class CustomUUIDGenerator implements IdGenerator {
+
+    @Override
+    public Serializable generate(Object entity) {
+        String name = (String) SystemMetaObject.forObject(entity).getValue("name");
+        if ("旺仔".equals(name)) {
+            return "66666666666";
+        } else if ("靓仔".equals(name)) {
+            return "77777777777";
+        }
+        return IdWorker.get32UUID();
+    }
+}

+ 2 - 1
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/idgenerator/IdGeneratorConfig.java

@@ -1,5 +1,6 @@
 package com.baomidou.mybatisplus.test.h2.idgenerator;
 
+import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.core.MybatisConfiguration;
 import com.baomidou.mybatisplus.core.config.GlobalConfig;
 import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
@@ -37,7 +38,7 @@ public class IdGeneratorConfig {
     public GlobalConfig globalConfiguration() {
         GlobalConfig conf = new GlobalConfig();
         //自定义Id生成器
-        conf.setIdGenerator(new CustomIdGenerator());
+        conf.registerIdGenerator(IdType.ASSIGN_UUID, new CustomUUIDGenerator()).registerIdGenerator(IdType.ASSIGN_ID, new CustomIdGenerator());
         return conf;
     }