1
0

feat: 使用优化后的、前端友好的雪花算法ID

This commit is contained in:
2025-08-26 16:08:12 +08:00
parent 7d548a4be1
commit 57c6e09fb0
3 changed files with 101 additions and 1 deletions

View File

@@ -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;

View File

@@ -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 {
}

View File

@@ -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();
}
}
}