diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/keygen/KeyGeneratorFactory.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/keygen/KeyGeneratorFactory.java index 895f3822..fd0d480b 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/keygen/KeyGeneratorFactory.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/keygen/KeyGeneratorFactory.java @@ -19,6 +19,7 @@ import com.mybatisflex.core.exception.FlexExceptions; import com.mybatisflex.core.exception.locale.LocalizedFormats; import com.mybatisflex.core.keygen.impl.FlexIDKeyGenerator; import com.mybatisflex.core.keygen.impl.SnowFlakeIDKeyGenerator; +import com.mybatisflex.core.keygen.impl.ULIDKeyGenerator; import com.mybatisflex.core.keygen.impl.UUIDKeyGenerator; import com.mybatisflex.core.util.StringUtil; @@ -39,6 +40,8 @@ public class KeyGeneratorFactory { register(KeyGenerators.uuid, new UUIDKeyGenerator()); register(KeyGenerators.flexId, new FlexIDKeyGenerator()); register(KeyGenerators.snowFlakeId, new SnowFlakeIDKeyGenerator()); + register(KeyGenerators.ulid, new ULIDKeyGenerator()); + } @@ -49,7 +52,7 @@ public class KeyGeneratorFactory { * @return 主键生成器 */ public static IKeyGenerator getKeyGenerator(String name) { - if (StringUtil.isBlank(name)){ + if (StringUtil.isBlank(name)) { throw FlexExceptions.wrap(LocalizedFormats.KEY_GENERATOR_BLANK); } return KEY_GENERATOR_MAP.get(name.trim()); diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/keygen/KeyGenerators.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/keygen/KeyGenerators.java index 90eee69b..062bc6eb 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/keygen/KeyGenerators.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/keygen/KeyGenerators.java @@ -38,4 +38,9 @@ public class KeyGenerators { */ public static final String snowFlakeId = "snowFlakeId"; + /** + * ulid 主键生成器 + * {@link com.mybatisflex.core.keygen.impl.ULIDKeyGenerator} + */ + public static final String ulid = "ulid"; } diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/keygen/impl/ULIDKeyGenerator.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/keygen/impl/ULIDKeyGenerator.java new file mode 100644 index 00000000..2bbb511c --- /dev/null +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/keygen/impl/ULIDKeyGenerator.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2022-2025, Mybatis-Flex (fuhai999@gmail.com). + *
+ * 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 + *
+ * http://www.apache.org/licenses/LICENSE-2.0 + *
+ * 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.mybatisflex.core.keygen.impl; + +import com.mybatisflex.core.keygen.IKeyGenerator; + +import java.util.concurrent.ThreadLocalRandom; + +/** + * ULID: 对比UUID的优势在于可排序性和性能。 + *
+ * 特点: + * 1、保证 id 生成的顺序为时间顺序,越往后生成的 ID 值越大; + * 2、可以按照生成的时间进行排序,而不需要全局协调; + * 3、生成速度快; + *
+ *
参考:Sequence
+ */
+public class ULIDKeyGenerator implements IKeyGenerator {
+
+ private static final char[] ENCODING_CHARS = {
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K',
+ 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'V', 'W', 'X',
+ 'Y', 'Z'
+ };
+
+ private static final long TIMESTAMP_OVERFLOW_MASK = 0xFFFF_0000_0000_0000L;
+
+ private static final ThreadLocal