HHH-18377 - Support for uuid v6 and v7 generated ids

This commit is contained in:
Steve Ebersole 2024-09-23 13:53:27 -05:00
parent 2f335cd786
commit c3d7e5f0b5
2 changed files with 20 additions and 42 deletions

View File

@ -14,6 +14,7 @@ import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
import org.hibernate.Internal;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.id.UUIDGenerationStrategy; import org.hibernate.id.UUIDGenerationStrategy;
@ -30,64 +31,51 @@ import org.hibernate.id.UUIDGenerationStrategy;
* <li>48 bits - pseudorandom data to provide uniqueness.</li> * <li>48 bits - pseudorandom data to provide uniqueness.</li>
* </ul> * </ul>
* *
* @apiNote This strategy is field-compatible with Version 1, with the time bits reordered for improved DB locality.
*
* @author Cedomir Igaly * @author Cedomir Igaly
*/ */
public class UuidVersion6Strategy implements UUIDGenerationStrategy, UuidValueGenerator { public class UuidVersion6Strategy implements UUIDGenerationStrategy, UuidValueGenerator {
private static final Instant EPOCH_1582; public static final UuidVersion6Strategy INSTANCE = new UuidVersion6Strategy();
static { private static final Instant EPOCH_1582 = LocalDate.of( 1582, 10, 15 )
EPOCH_1582 = LocalDate.of( 1582, 10, 15 ) .atStartOfDay( ZoneId.of( "UTC" ) )
.atStartOfDay( ZoneId.of( "UTC" ) ) .toInstant();
.toInstant();
}
private static class Holder { private static class Holder {
static final SecureRandom numberGenerator = new SecureRandom(); static final SecureRandom numberGenerator = new SecureRandom();
} }
public static final UuidVersion6Strategy INSTANCE = new UuidVersion6Strategy();
private final Lock lock = new ReentrantLock( true ); private final Lock lock = new ReentrantLock( true );
private final AtomicLong clockSequence = new AtomicLong( 0 );
private long currentTimestamp; private long currentTimestamp;
private final AtomicLong clockSequence = new AtomicLong( 0 );
@Internal
public UuidVersion6Strategy() { public UuidVersion6Strategy() {
this( getCurrentTimestamp(), 0 ); this( getCurrentTimestamp(), 0 );
} }
@Internal
public UuidVersion6Strategy(final long currentTimestamp, final long clockSequence) { public UuidVersion6Strategy(final long currentTimestamp, final long clockSequence) {
this.currentTimestamp = currentTimestamp; this.currentTimestamp = currentTimestamp;
this.clockSequence.set( clockSequence ); this.clockSequence.set( clockSequence );
} }
/** /**
* A variant 6 * Version 6
*/ */
@Override @Override
public int getGeneratedVersion() { public int getGeneratedVersion() {
// UUIDv6 is a field-compatible version of UUIDv1, reordered for improved DB locality
return 6; return 6;
} }
/**
* Delegates to {@link #generateUuid}
*/
@Override @Override
public UUID generateUUID(SharedSessionContractImplementor session) { public UUID generateUUID(SharedSessionContractImplementor session) {
return generateUuid( session ); return generateUuid( session );
} }
/**
* @param session session
*
* @return UUID version 6
* @see UuidValueGenerator#generateUuid(SharedSessionContractImplementor)
*/
@Override @Override
public UUID generateUuid(SharedSessionContractImplementor session) { public UUID generateUuid(SharedSessionContractImplementor session) {
final long currentTimestamp = getCurrentTimestamp(); final long currentTimestamp = getCurrentTimestamp();

View File

@ -12,6 +12,7 @@ import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
import org.hibernate.Internal;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.id.UUIDGenerationStrategy; import org.hibernate.id.UUIDGenerationStrategy;
@ -33,6 +34,10 @@ import static java.time.temporal.ChronoUnit.MILLIS;
* <li>48 bits - pseudorandom data to provide uniqueness.</li> * <li>48 bits - pseudorandom data to provide uniqueness.</li>
* </ul> * </ul>
* *
* @apiNote Version 7 features a time-ordered value field derived from the widely implemented and
* well-known Unix Epoch timestamp source, the number of milliseconds since midnight 1 Jan 1970 UTC,
* leap seconds excluded.
*
* @author Cedomir Igaly * @author Cedomir Igaly
*/ */
public class UuidVersion7Strategy implements UUIDGenerationStrategy, UuidValueGenerator { public class UuidVersion7Strategy implements UUIDGenerationStrategy, UuidValueGenerator {
@ -40,52 +45,37 @@ public class UuidVersion7Strategy implements UUIDGenerationStrategy, UuidValueGe
public static final UuidVersion7Strategy INSTANCE = new UuidVersion7Strategy(); public static final UuidVersion7Strategy INSTANCE = new UuidVersion7Strategy();
private static class Holder { private static class Holder {
static final SecureRandom numberGenerator = new SecureRandom(); static final SecureRandom numberGenerator = new SecureRandom();
} }
private final Lock lock = new ReentrantLock( true ); private final Lock lock = new ReentrantLock( true );
private final AtomicLong clockSequence;
private Duration currentTimestamp; private Duration currentTimestamp;
private final AtomicLong clockSequence; @Internal
public UuidVersion7Strategy() { public UuidVersion7Strategy() {
this( getCurrentTimestamp(), 0 ); this( getCurrentTimestamp(), 0 );
} }
@Internal
public UuidVersion7Strategy(final Duration currentTimestamp, final long clockSequence) { public UuidVersion7Strategy(final Duration currentTimestamp, final long clockSequence) {
this.currentTimestamp = currentTimestamp; this.currentTimestamp = currentTimestamp;
this.clockSequence = new AtomicLong( clockSequence ); this.clockSequence = new AtomicLong( clockSequence );
} }
/** /**
* A variant 7 * Version 7
*/ */
@Override @Override
public int getGeneratedVersion() { public int getGeneratedVersion() {
/*
* UUIDv7 features a time-ordered value field derived from the widely implemented and well-
* known Unix Epoch timestamp source, the number of milliseconds since midnight 1 Jan 1970 UTC,
* leap seconds excluded.
*/
return 7; return 7;
} }
/**
* Delegates to {@link #generateUuid}
*/
@Override @Override
public UUID generateUUID(SharedSessionContractImplementor session) { public UUID generateUUID(SharedSessionContractImplementor session) {
return generateUuid( session ); return generateUuid( session );
} }
/**
* @param session session
*
* @return UUID version 7
* @see UuidValueGenerator#generateUuid(SharedSessionContractImplementor)
*/
@Override @Override
public UUID generateUuid(SharedSessionContractImplementor session) { public UUID generateUuid(SharedSessionContractImplementor session) {
final Duration currentTimestamp = getCurrentTimestamp(); final Duration currentTimestamp = getCurrentTimestamp();