diff --git a/src/main/java/com/lanyuanxiaoyao/service/template/entity/IdOnlyEntity.java b/src/main/java/com/lanyuanxiaoyao/service/template/entity/IdOnlyEntity.java index 583be10..b531473 100644 --- a/src/main/java/com/lanyuanxiaoyao/service/template/entity/IdOnlyEntity.java +++ b/src/main/java/com/lanyuanxiaoyao/service/template/entity/IdOnlyEntity.java @@ -1,6 +1,6 @@ package com.lanyuanxiaoyao.service.template.entity; -import com.blinkfox.fenix.id.SnowflakeId; +import com.lanyuanxiaoyao.service.template.helper.SnowflakeId; import jakarta.persistence.EntityListeners; import jakarta.persistence.Id; import jakarta.persistence.MappedSuperclass; diff --git a/src/main/java/com/lanyuanxiaoyao/service/template/helper/SnowflakeId.java b/src/main/java/com/lanyuanxiaoyao/service/template/helper/SnowflakeId.java new file mode 100644 index 0000000..f42da4b --- /dev/null +++ b/src/main/java/com/lanyuanxiaoyao/service/template/helper/SnowflakeId.java @@ -0,0 +1,13 @@ +package com.lanyuanxiaoyao.service.template.helper; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.hibernate.annotations.IdGeneratorType; + +@IdGeneratorType(SnowflakeIdGenerator.class) +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.FIELD, ElementType.METHOD }) +public @interface SnowflakeId { +} diff --git a/src/main/java/com/lanyuanxiaoyao/service/template/helper/SnowflakeIdGenerator.java b/src/main/java/com/lanyuanxiaoyao/service/template/helper/SnowflakeIdGenerator.java new file mode 100644 index 0000000..9f20a36 --- /dev/null +++ b/src/main/java/com/lanyuanxiaoyao/service/template/helper/SnowflakeIdGenerator.java @@ -0,0 +1,87 @@ +package com.lanyuanxiaoyao.service.template.helper; + +import java.io.Serializable; +import java.time.Instant; +import lombok.extern.slf4j.Slf4j; +import org.hibernate.engine.spi.SharedSessionContractImplementor; +import org.hibernate.id.IdentifierGenerator; +import org.hibernate.id.factory.spi.StandardGenerator; + +@Slf4j +public class SnowflakeIdGenerator implements IdentifierGenerator, StandardGenerator { + + @Override + public Serializable generate(SharedSessionContractImplementor session, Object object) { + try { + return Snowflake.next(); + } catch (Exception e) { + log.error("Generate snowflake id failed", e); + throw new RuntimeException(e); + } + } + + public static class Snowflake { + /** + * 起始的时间戳 + */ + private final static long START_TIMESTAMP = 1; + + /** + * 序列号占用的位数 + */ + private final static long SEQUENCE_BIT = 11; + + /** + * 序列号最大值 + */ + private final static long MAX_SEQUENCE_BIT = ~(-1 << SEQUENCE_BIT); + + /** + * 时间戳值向左位移 + */ + private final static long TIMESTAMP_OFFSET = SEQUENCE_BIT; + + /** + * 序列号 + */ + private static long sequence = 0; + /** + * 上一次时间戳 + */ + private static long lastTimestamp = -1; + + public static synchronized long next() { + long currentTimestamp = nowTimestamp(); + if (currentTimestamp < lastTimestamp) { + throw new RuntimeException("Clock have moved backwards."); + } + + if (currentTimestamp == lastTimestamp) { + // 相同毫秒内, 序列号自增 + sequence = (sequence + 1) & MAX_SEQUENCE_BIT; + // 同一毫秒的序列数已经达到最大 + if (sequence == 0) { + currentTimestamp = nextTimestamp(); + } + } else { + // 不同毫秒内, 序列号置为0 + sequence = 0; + } + + lastTimestamp = currentTimestamp; + return (currentTimestamp - START_TIMESTAMP) << TIMESTAMP_OFFSET | sequence; + } + + private static long nextTimestamp() { + long milli = nowTimestamp(); + while (milli <= lastTimestamp) { + milli = nowTimestamp(); + } + return milli; + } + + private static long nowTimestamp() { + return Instant.now().toEpochMilli(); + } + } +}