HHH-18411 - Add ability to specify a custom UuidGenerator.ValueGenerator

This commit is contained in:
Steve Ebersole 2024-07-24 14:55:26 -05:00
parent fdef3b52eb
commit 2f3a01fd19
27 changed files with 1239 additions and 38 deletions

View File

@ -306,6 +306,7 @@ The most important piece of information here is the specified `jakarta.persisten
`IDENTITY`:: Indicates that database IDENTITY columns will be used for primary key value generation. See <<identifiers-generators-identity>>.
`SEQUENCE`:: Indicates that database sequence should be used for obtaining primary key values. See <<identifiers-generators-sequence>>.
`TABLE`:: Indicates that a database table should be used for obtaining primary key values. See <<identifiers-generators-table>>.
`UUID`:::Indicates that UUID generation should be used. See <<identifiers-generators-uuid>>
[[identifiers-generators-auto]]
==== Interpreting AUTO
@ -314,7 +315,7 @@ How a persistence provider interprets the AUTO generation type is left up to the
The default behavior is to look at the Java type of the identifier attribute, plus what the underlying database supports.
If the identifier type is UUID, Hibernate is going to use a <<identifiers-generators-uuid, UUID identifier>>.
If the identifier type is UUID, Hibernate is going to use a <<identifiers-generators-uuid, UUID generator>>.
If the identifier type is numeric (e.g. `Long`, `Integer`), then Hibernate will use its `SequenceStyleGenerator` which
resolves to a SEQUENCE generation if the underlying database supports sequences and a table-based generation otherwise.
@ -500,38 +501,122 @@ include::{extrasdir}/id/identifiers-generators-table-configured-persist-example.
[[identifiers-generators-uuid]]
==== Using UUID generation
As mentioned above, Hibernate supports UUID identifier value generation.
This is supported through its `org.hibernate.id.UUIDGenerator` id generator.
Hibernate offers 2 flavors of support for UUID generation -
NOTE:: `org.hibernate.id.UUIDGenerator` is an example of `@IdGeneratorType` discussed in <<identifiers-generators-IdGeneratorType>>
1. using `org.hibernate.id.uuid.UuidGenerator`, which can be configured using the `org.hibernate.annotations.UuidGenerator` annotation.
2. using `org.hibernate.id.UUIDGenerator`, which can be configured using the `@GenericGenerator` annotation. Note that this approach is deprecated.
For legacy reasons, `org.hibernate.id.UUIDGenerator` is used when the generator is implicit (or explicitly requested via `@GenericGenerator`).
`UUIDGenerator` supports pluggable strategies for exactly how the UUID is generated.
These strategies are defined by the `org.hibernate.id.UUIDGenerationStrategy` contract.
The default strategy is a version 4 (random) strategy according to IETF RFC 4122.
Hibernate does ship with an alternative strategy which is a RFC 4122 version 1 (time-based) strategy (using IP address rather than mac address).
[NOTE]
====
Future versions of Hibernate will drop support for `org.hibernate.id.UUIDGenerator` and the following 3 examples
will then use `org.hibernate.id.uuid.UuidGenerator`.
====
[[identifiers-generators-uuid-mapping-example]]
.Implicitly using the random UUID strategy
[[example-identifiers-generators-uuid-implicit]]
.Implicit UUID generation
====
[source,java]
----
include::{example-dir-identifier}/UuidGeneratedValueTest.java[tag=identifiers-generators-uuid-mapping-example, indent=0]
include::{example-dir-identifier}/uuid/implicit/Book.java[tag=example-identifiers-generators-uuid-implicit, indent=0]
----
====
To specify an alternative generation strategy, we'd have to define some configuration via `@GenericGenerator`.
Here we choose the RFC 4122 version 1 compliant strategy named `org.hibernate.id.uuid.CustomVersionOneStrategy`.
[[identifiers-generators-custom-uuid-mapping-example]]
.Implicitly using the random UUID strategy
[[example-identifiers-generators-uuid-implicit2]]
.Another example of implicit UUID generation
====
[source,java]
----
include::{example-dir-identifier}/UuidCustomGeneratedValueTest.java[tag=identifiers-generators-custom-uuid-mapping-example, indent=0]
include::{example-dir-identifier}/uuid/implicit2/Book.java[tag=example-identifiers-generators-uuid-implicit, indent=0]
----
====
[[example-identifiers-generators-uuid-implicit3]]
.Implicit UUID generation with String
====
[source,java]
----
include::{example-dir-identifier}/uuid/implicit3/Book.java[tag=example-identifiers-generators-uuid-implicit, indent=0]
----
====
The second approach, using `org.hibernate.id.uuid.UuidGenerator`, is much more flexible and usable
because it builds on top of the <<identifiers-generators-IdGeneratorType,@IdGeneratorType>> support.
To use (and optionally configure) this strategy, use the `org.hibernate.annotations.UuidGenerator` annotation.
By default, Hibernate uses a random (IETF RFC 4122 version 4) generation.
[[example-identifiers-generators-uuid-random]]
.Random UUID generation
====
[source,java]
----
include::{example-dir-identifier}/uuid/random/Book.java[tag=example-identifiers-generators-uuid-implicit, indent=0]
----
====
[[example-identifiers-generators-uuid-random2]]
.Random UUID generation, with explicit style
====
[source,java]
----
include::{example-dir-identifier}/uuid/random2/Book.java[tag=example-identifiers-generators-uuid-implicit, indent=0]
----
====
[[example-identifiers-generators-uuid-random3]]
.Random UUID generation, with String
====
[source,java]
----
include::{example-dir-identifier}/uuid/random3/Book.java[tag=example-identifiers-generators-uuid-implicit, indent=0]
----
====
Hibernate also comes with simplified support for a time-based (IETF RFC 4122 version 1, variant2) generation.
[[example-identifiers-generators-uuid-time]]
.Time-based UUID generation
====
[source,java]
----
include::{example-dir-identifier}/uuid/time/Book.java[tag=example-identifiers-generators-uuid-implicit, indent=0]
----
====
[[example-identifiers-generators-uuid-time2]]
.Time-based UUID generation using String
====
[source,java]
----
include::{example-dir-identifier}/uuid/time2/Book.java[tag=example-identifiers-generators-uuid-implicit, indent=0]
----
====
For even more flexibility, Hibernate also offers the ability to plug in custom algorithms for creating the UUID value
by specifying an implementation of `org.hibernate.id.uuid.UuidValueGenerator`.
[[example-identifiers-generators-uuid-custom]]
.Custom UUID generation
====
[source,java]
----
include::{example-dir-identifier}/uuid/custom/Book.java[tag=example-identifiers-generators-uuid-implicit, indent=0]
----
====
[[example-identifiers-generators-uuid-custom2]]
.Custom UUID generation using String
====
[source,java]
----
include::{example-dir-identifier}/uuid/custom2/Book.java[tag=example-identifiers-generators-uuid-implicit, indent=0]
----
====
[[identifiers-generators-optimizer]]
==== Optimizers

View File

@ -40,6 +40,15 @@ public class UuidGenerator implements BeforeExecutionGenerator {
private final UuidValueGenerator generator;
private final ValueTransformer valueTransformer;
/**
* This form is used when there is no {@code @UuidGenerator} but we know we want this generator
*/
@Internal
public UuidGenerator(Class<?> memberType) {
generator = StandardRandomStrategy.INSTANCE;
valueTransformer = determineProperTransformer( memberType );
}
private UuidGenerator(
org.hibernate.annotations.UuidGenerator config,
Member idMember) {
@ -65,19 +74,7 @@ public class UuidGenerator implements BeforeExecutionGenerator {
}
final Class<?> propertyType = getPropertyType( idMember );
if ( UUID.class.isAssignableFrom( propertyType ) ) {
valueTransformer = UUIDJavaType.PassThroughTransformer.INSTANCE;
}
else if ( String.class.isAssignableFrom( propertyType ) ) {
valueTransformer = UUIDJavaType.ToStringTransformer.INSTANCE;
}
else if ( byte[].class.isAssignableFrom( propertyType ) ) {
valueTransformer = UUIDJavaType.ToBytesTransformer.INSTANCE;
}
else {
throw new HibernateException( "Unanticipated return type [" + propertyType.getName() + "] for UUID conversion" );
}
this.valueTransformer = determineProperTransformer( propertyType );
}
private static UuidValueGenerator instantiateCustomGenerator(Class<? extends UuidValueGenerator> algorithmClass) {
@ -89,6 +86,22 @@ public class UuidGenerator implements BeforeExecutionGenerator {
}
}
private ValueTransformer determineProperTransformer(Class<?> propertyType) {
if ( UUID.class.isAssignableFrom( propertyType ) ) {
return UUIDJavaType.PassThroughTransformer.INSTANCE;
}
if ( String.class.isAssignableFrom( propertyType ) ) {
return UUIDJavaType.ToStringTransformer.INSTANCE;
}
if ( byte[].class.isAssignableFrom( propertyType ) ) {
return UUIDJavaType.ToBytesTransformer.INSTANCE;
}
throw new HibernateException( "Unanticipated return type [" + propertyType.getName() + "] for UUID conversion" );
}
public UuidGenerator(
org.hibernate.annotations.UuidGenerator config,
Member idMember,

View File

@ -8,24 +8,19 @@ package org.hibernate.orm.test.id.uuid.annotation;
import java.util.UUID;
import org.hibernate.boot.model.relational.Database;
import org.hibernate.dialect.SybaseDialect;
import org.hibernate.generator.Generator;
import org.hibernate.id.factory.IdentifierGeneratorFactory;
import org.hibernate.id.factory.spi.CustomIdGeneratorCreationContext;
import org.hibernate.id.uuid.StandardRandomStrategy;
import org.hibernate.id.uuid.UuidGenerator;
import org.hibernate.mapping.BasicValue;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property;
import org.hibernate.mapping.RootClass;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.DomainModelScope;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.hibernate.testing.orm.junit.SkipForDialect;
import org.hibernate.testing.util.uuid.IdGeneratorCreationContext;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;

View File

@ -0,0 +1,45 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
*/
package org.hibernate.orm.test.mapping.identifier.uuid;
import org.hibernate.generator.Generator;
import org.hibernate.id.uuid.UuidGenerator;
import org.hibernate.id.uuid.UuidValueGenerator;
import org.hibernate.mapping.BasicValue;
import org.hibernate.mapping.Property;
import org.hibernate.mapping.RootClass;
import org.hibernate.testing.orm.junit.DomainModelScope;
import org.hibernate.testing.orm.junit.ServiceRegistryScope;
import org.hibernate.testing.util.uuid.IdGeneratorCreationContext;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Steve Ebersole
*/
public class Helper {
public static void verifyAlgorithm(
ServiceRegistryScope registryScope,
DomainModelScope domainModelScope,
RootClass descriptor,
Class<? extends UuidValueGenerator> expectedAlgorithm) {
final Property idProperty = descriptor.getIdentifierProperty();
final BasicValue value = (BasicValue) idProperty.getValue();
assertThat( value.getCustomIdGeneratorCreator() ).isNotNull();
final Generator generator = value.getCustomIdGeneratorCreator().createGenerator( new IdGeneratorCreationContext(
registryScope.getRegistry(),
domainModelScope.getDomainModel(),
descriptor
));
assertThat( generator ).isInstanceOf( UuidGenerator.class );
final UuidGenerator uuidGenerator = (UuidGenerator) generator;
assertThat( uuidGenerator.getValueGenerator() ).isInstanceOf( expectedAlgorithm );
}
}

View File

@ -0,0 +1,56 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
*/
package org.hibernate.orm.test.mapping.identifier.uuid.custom;
import java.util.UUID;
import org.hibernate.annotations.UuidGenerator;
import jakarta.persistence.Basic;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import static org.hibernate.annotations.UuidGenerator.Style.TIME;
/**
* @author Steve Ebersole
*/
//tag::example-identifiers-generators-uuid-implicit[]
@Entity
public class Book {
@Id
@GeneratedValue
@UuidGenerator(algorithm = CustomUuidValueCreator.class)
private UUID id;
@Basic
private String name;
//end::example-identifiers-generators-uuid-implicit[]
protected Book() {
// for Hibernate use
}
public Book(String name) {
this.name = name;
}
public UUID getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//tag::example-identifiers-generators-uuid-implicit[]
}
//end::example-identifiers-generators-uuid-implicit[]

View File

@ -0,0 +1,46 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
*/
package org.hibernate.orm.test.mapping.identifier.uuid.custom;
import org.hibernate.orm.test.mapping.identifier.uuid.Helper;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.DomainModelScope;
import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.ServiceRegistryScope;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.Test;
/**
* @author Steve Ebersole
*/
@SuppressWarnings("JUnitMalformedDeclaration")
public class CustomUuidGenerationTests {
@Test
@ServiceRegistry
@DomainModel(annotatedClasses = Book.class)
void verifyModel(ServiceRegistryScope registryScope, DomainModelScope domainModelScope) {
domainModelScope.withHierarchy( Book.class, (descriptor) -> {
Helper.verifyAlgorithm( registryScope, domainModelScope, descriptor, CustomUuidValueCreator.class );
} );
}
@Test
@ServiceRegistry
@DomainModel(annotatedClasses = Book.class)
@SessionFactory
void testUsage(SessionFactoryScope scope) {
scope.inTransaction( (session) -> {
session.persist( new Book() );
} );
scope.inTransaction( (session) -> {
session.createMutationQuery( "delete Book" ).executeUpdate();
} );
}
}

View File

@ -0,0 +1,22 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
*/
package org.hibernate.orm.test.mapping.identifier.uuid.custom;
import java.util.UUID;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.id.uuid.UuidValueGenerator;
/**
* @author Steve Ebersole
*/
public class CustomUuidValueCreator implements UuidValueGenerator {
@Override
public UUID generateUuid(SharedSessionContractImplementor session) {
return UUID.randomUUID();
}
}

View File

@ -0,0 +1,53 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
*/
package org.hibernate.orm.test.mapping.identifier.uuid.custom2;
import org.hibernate.annotations.UuidGenerator;
import org.hibernate.orm.test.mapping.identifier.uuid.custom.CustomUuidValueCreator;
import jakarta.persistence.Basic;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
/**
* @author Steve Ebersole
*/
//tag::example-identifiers-generators-uuid-implicit[]
@Entity
public class Book {
@Id
@GeneratedValue
@UuidGenerator(algorithm = CustomUuidValueCreator.class)
private String id;
@Basic
private String name;
//end::example-identifiers-generators-uuid-implicit[]
protected Book() {
// for Hibernate use
}
public Book(String name) {
this.name = name;
}
public String getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//tag::example-identifiers-generators-uuid-implicit[]
}
//end::example-identifiers-generators-uuid-implicit[]

View File

@ -0,0 +1,47 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
*/
package org.hibernate.orm.test.mapping.identifier.uuid.custom2;
import org.hibernate.orm.test.mapping.identifier.uuid.Helper;
import org.hibernate.orm.test.mapping.identifier.uuid.custom.CustomUuidValueCreator;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.DomainModelScope;
import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.ServiceRegistryScope;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.Test;
/**
* @author Steve Ebersole
*/
@SuppressWarnings("JUnitMalformedDeclaration")
public class CustomUuidGenerationTests {
@Test
@ServiceRegistry
@DomainModel(annotatedClasses = Book.class)
void verifyModel(ServiceRegistryScope registryScope, DomainModelScope domainModelScope) {
domainModelScope.withHierarchy( Book.class, (descriptor) -> {
Helper.verifyAlgorithm( registryScope, domainModelScope, descriptor, CustomUuidValueCreator.class );
} );
}
@Test
@ServiceRegistry
@DomainModel(annotatedClasses = Book.class)
@SessionFactory
void testUsage(SessionFactoryScope scope) {
scope.inTransaction( (session) -> {
session.persist( new Book() );
} );
scope.inTransaction( (session) -> {
session.createMutationQuery( "delete Book" ).executeUpdate();
} );
}
}

View File

@ -0,0 +1,51 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
*/
package org.hibernate.orm.test.mapping.identifier.uuid.implicit;
import java.util.UUID;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.Basic;
/**
* @author Steve Ebersole
*/
//tag::example-identifiers-generators-uuid-implicit[]
@Entity
public class Book {
@Id
@GeneratedValue
private UUID id;
@Basic
private String name;
//end::example-identifiers-generators-uuid-implicit[]
protected Book() {
// for Hibernate use
}
public Book(String name) {
this.name = name;
}
public UUID getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//tag::example-identifiers-generators-uuid-implicit[]
}
//end::example-identifiers-generators-uuid-implicit[]

View File

@ -0,0 +1,49 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
*/
package org.hibernate.orm.test.mapping.identifier.uuid.implicit;
import org.hibernate.id.uuid.StandardRandomStrategy;
import org.hibernate.orm.test.mapping.identifier.uuid.Helper;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.DomainModelScope;
import org.hibernate.testing.orm.junit.FailureExpected;
import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.ServiceRegistryScope;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.Test;
/**
* @author Steve Ebersole
*/
@SuppressWarnings("JUnitMalformedDeclaration")
public class ImplicitUuidGenerationTests {
@Test
@ServiceRegistry
@DomainModel(annotatedClasses = Book.class)
@FailureExpected( jiraKey = "HHH-18420", reason = "Implicit UUID generation continues to use UUIDGenerator for the time being" )
void verifyModel(ServiceRegistryScope registryScope, DomainModelScope domainModelScope) {
domainModelScope.withHierarchy( Book.class, (descriptor) -> {
Helper.verifyAlgorithm( registryScope, domainModelScope, descriptor, StandardRandomStrategy.class );
} );
}
@Test
@ServiceRegistry
@DomainModel(annotatedClasses = Book.class)
@SessionFactory
void testUsage(SessionFactoryScope scope) {
scope.inTransaction( (session) -> {
session.persist( new Book() );
} );
scope.inTransaction( (session) -> {
session.createMutationQuery( "delete Book" ).executeUpdate();
} );
}
}

View File

@ -0,0 +1,52 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
*/
package org.hibernate.orm.test.mapping.identifier.uuid.implicit2;
import java.util.UUID;
import jakarta.persistence.Basic;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
/**
* @author Steve Ebersole
*/
//tag::example-identifiers-generators-uuid-implicit[]
@Entity
public class Book {
@Id
@GeneratedValue(strategy = GenerationType.UUID)
private UUID id;
@Basic
private String name;
//end::example-identifiers-generators-uuid-implicit[]
protected Book() {
// for Hibernate use
}
public Book(String name) {
this.name = name;
}
public UUID getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//tag::example-identifiers-generators-uuid-implicit[]
}
//end::example-identifiers-generators-uuid-implicit[]

View File

@ -0,0 +1,49 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
*/
package org.hibernate.orm.test.mapping.identifier.uuid.implicit2;
import org.hibernate.id.uuid.StandardRandomStrategy;
import org.hibernate.orm.test.mapping.identifier.uuid.Helper;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.DomainModelScope;
import org.hibernate.testing.orm.junit.FailureExpected;
import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.ServiceRegistryScope;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.Test;
/**
* @author Steve Ebersole
*/
@SuppressWarnings("JUnitMalformedDeclaration")
public class Implicit2UuidGenerationTests {
@Test
@ServiceRegistry
@DomainModel(annotatedClasses = Book.class)
@FailureExpected( jiraKey = "HHH-18420", reason = "Implicit UUID generation continues to use UUIDGenerator for the time being" )
void verifyModel(ServiceRegistryScope registryScope, DomainModelScope domainModelScope) {
domainModelScope.withHierarchy( Book.class, (descriptor) -> {
Helper.verifyAlgorithm( registryScope, domainModelScope, descriptor, StandardRandomStrategy.class );
} );
}
@Test
@ServiceRegistry
@DomainModel(annotatedClasses = Book.class)
@SessionFactory
void testUsage(SessionFactoryScope scope) {
scope.inTransaction( (session) -> {
session.persist( new Book() );
} );
scope.inTransaction( (session) -> {
session.createMutationQuery( "delete Book" ).executeUpdate();
} );
}
}

View File

@ -0,0 +1,52 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
*/
package org.hibernate.orm.test.mapping.identifier.uuid.implicit3;
import java.util.UUID;
import jakarta.persistence.Basic;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
/**
* @author Steve Ebersole
*/
//tag::example-identifiers-generators-uuid-implicit[]
@Entity
public class Book {
@Id
@GeneratedValue(strategy = GenerationType.UUID)
private String id;
@Basic
private String name;
//end::example-identifiers-generators-uuid-implicit[]
protected Book() {
// for Hibernate use
}
public Book(String name) {
this.name = name;
}
public String getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//tag::example-identifiers-generators-uuid-implicit[]
}
//end::example-identifiers-generators-uuid-implicit[]

View File

@ -0,0 +1,49 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
*/
package org.hibernate.orm.test.mapping.identifier.uuid.implicit3;
import org.hibernate.id.uuid.StandardRandomStrategy;
import org.hibernate.orm.test.mapping.identifier.uuid.Helper;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.DomainModelScope;
import org.hibernate.testing.orm.junit.FailureExpected;
import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.ServiceRegistryScope;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.Test;
/**
* @author Steve Ebersole
*/
@SuppressWarnings("JUnitMalformedDeclaration")
public class Implicit3UuidGenerationTests {
@Test
@ServiceRegistry
@DomainModel(annotatedClasses = Book.class)
@FailureExpected( jiraKey = "HHH-18420", reason = "Implicit UUID generation continues to use UUIDGenerator for the time being" )
void verifyModel(ServiceRegistryScope registryScope, DomainModelScope domainModelScope) {
domainModelScope.withHierarchy( Book.class, (descriptor) -> {
Helper.verifyAlgorithm( registryScope, domainModelScope, descriptor, StandardRandomStrategy.class );
} );
}
@Test
@ServiceRegistry
@DomainModel(annotatedClasses = Book.class)
@SessionFactory
void testUsage(SessionFactoryScope scope) {
scope.inTransaction( (session) -> {
session.persist( new Book() );
} );
scope.inTransaction( (session) -> {
session.createMutationQuery( "delete Book" ).executeUpdate();
} );
}
}

View File

@ -0,0 +1,13 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
*/
/**
* These classes and tests are used in the user-guide
*
* @author Steve Ebersole
*/
package org.hibernate.orm.test.mapping.identifier.uuid;

View File

@ -0,0 +1,54 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
*/
package org.hibernate.orm.test.mapping.identifier.uuid.random;
import java.util.UUID;
import org.hibernate.annotations.UuidGenerator;
import jakarta.persistence.Basic;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
/**
* @author Steve Ebersole
*/
//tag::example-identifiers-generators-uuid-implicit[]
@Entity
public class Book {
@Id
@GeneratedValue
@UuidGenerator
private UUID id;
@Basic
private String name;
//end::example-identifiers-generators-uuid-implicit[]
protected Book() {
// for Hibernate use
}
public Book(String name) {
this.name = name;
}
public UUID getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//tag::example-identifiers-generators-uuid-implicit[]
}
//end::example-identifiers-generators-uuid-implicit[]

View File

@ -0,0 +1,48 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
*/
package org.hibernate.orm.test.mapping.identifier.uuid.random;
import org.hibernate.id.uuid.CustomVersionOneStrategy;
import org.hibernate.id.uuid.StandardRandomStrategy;
import org.hibernate.orm.test.mapping.identifier.uuid.Helper;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.DomainModelScope;
import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.ServiceRegistryScope;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.Test;
/**
* @author Steve Ebersole
*/
@SuppressWarnings("JUnitMalformedDeclaration")
public class RandomBasedUuidGenerationTests {
@Test
@ServiceRegistry
@DomainModel(annotatedClasses = Book.class)
void verifyModel(ServiceRegistryScope registryScope, DomainModelScope domainModelScope) {
domainModelScope.withHierarchy( Book.class, (descriptor) -> {
Helper.verifyAlgorithm( registryScope, domainModelScope, descriptor, StandardRandomStrategy.class );
} );
}
@Test
@ServiceRegistry
@DomainModel(annotatedClasses = Book.class)
@SessionFactory
void testUsage(SessionFactoryScope scope) {
scope.inTransaction( (session) -> {
session.persist( new Book() );
} );
scope.inTransaction( (session) -> {
session.createMutationQuery( "delete Book" ).executeUpdate();
} );
}
}

View File

@ -0,0 +1,56 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
*/
package org.hibernate.orm.test.mapping.identifier.uuid.random2;
import java.util.UUID;
import org.hibernate.annotations.UuidGenerator;
import jakarta.persistence.Basic;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import static org.hibernate.annotations.UuidGenerator.Style.RANDOM;
/**
* @author Steve Ebersole
*/
//tag::example-identifiers-generators-uuid-implicit[]
@Entity
public class Book {
@Id
@GeneratedValue
@UuidGenerator(style = RANDOM)
private UUID id;
@Basic
private String name;
//end::example-identifiers-generators-uuid-implicit[]
protected Book() {
// for Hibernate use
}
public Book(String name) {
this.name = name;
}
public UUID getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//tag::example-identifiers-generators-uuid-implicit[]
}
//end::example-identifiers-generators-uuid-implicit[]

View File

@ -0,0 +1,47 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
*/
package org.hibernate.orm.test.mapping.identifier.uuid.random2;
import org.hibernate.id.uuid.StandardRandomStrategy;
import org.hibernate.orm.test.mapping.identifier.uuid.Helper;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.DomainModelScope;
import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.ServiceRegistryScope;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.Test;
/**
* @author Steve Ebersole
*/
@SuppressWarnings("JUnitMalformedDeclaration")
public class RandomBasedUuidGenerationTests {
@Test
@ServiceRegistry
@DomainModel(annotatedClasses = Book.class)
void verifyModel(ServiceRegistryScope registryScope, DomainModelScope domainModelScope) {
domainModelScope.withHierarchy( Book.class, (descriptor) -> {
Helper.verifyAlgorithm( registryScope, domainModelScope, descriptor, StandardRandomStrategy.class );
} );
}
@Test
@ServiceRegistry
@DomainModel(annotatedClasses = Book.class)
@SessionFactory
void testUsage(SessionFactoryScope scope) {
scope.inTransaction( (session) -> {
session.persist( new Book() );
} );
scope.inTransaction( (session) -> {
session.createMutationQuery( "delete Book" ).executeUpdate();
} );
}
}

View File

@ -0,0 +1,53 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
*/
package org.hibernate.orm.test.mapping.identifier.uuid.random3;
import org.hibernate.annotations.UuidGenerator;
import jakarta.persistence.Basic;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
/**
* @author Steve Ebersole
*/
//tag::example-identifiers-generators-uuid-implicit[]
@Entity
public class Book {
@Id
@GeneratedValue(strategy = GenerationType.UUID)
@UuidGenerator
private String id;
@Basic
private String name;
//end::example-identifiers-generators-uuid-implicit[]
protected Book() {
// for Hibernate use
}
public Book(String name) {
this.name = name;
}
public String getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//tag::example-identifiers-generators-uuid-implicit[]
}
//end::example-identifiers-generators-uuid-implicit[]

View File

@ -0,0 +1,47 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
*/
package org.hibernate.orm.test.mapping.identifier.uuid.random3;
import org.hibernate.id.uuid.StandardRandomStrategy;
import org.hibernate.orm.test.mapping.identifier.uuid.Helper;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.DomainModelScope;
import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.ServiceRegistryScope;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.Test;
/**
* @author Steve Ebersole
*/
@SuppressWarnings("JUnitMalformedDeclaration")
public class RandomBasedUuidGenerationTests {
@Test
@ServiceRegistry
@DomainModel(annotatedClasses = Book.class)
void verifyModel(ServiceRegistryScope registryScope, DomainModelScope domainModelScope) {
domainModelScope.withHierarchy( Book.class, (descriptor) -> {
Helper.verifyAlgorithm( registryScope, domainModelScope, descriptor, StandardRandomStrategy.class );
} );
}
@Test
@ServiceRegistry
@DomainModel(annotatedClasses = Book.class)
@SessionFactory
void testUsage(SessionFactoryScope scope) {
scope.inTransaction( (session) -> {
session.persist( new Book() );
} );
scope.inTransaction( (session) -> {
session.createMutationQuery( "delete Book" ).executeUpdate();
} );
}
}

View File

@ -0,0 +1,57 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
*/
package org.hibernate.orm.test.mapping.identifier.uuid.time;
import java.util.UUID;
import org.hibernate.annotations.UuidGenerator;
import jakarta.persistence.Basic;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import static org.hibernate.annotations.UuidGenerator.Style.TIME;
/**
* @author Steve Ebersole
*/
//tag::example-identifiers-generators-uuid-implicit[]
@Entity
public class Book {
@Id
@GeneratedValue
@UuidGenerator(style = TIME)
private UUID id;
@Basic
private String name;
//end::example-identifiers-generators-uuid-implicit[]
protected Book() {
// for Hibernate use
}
public Book(String name) {
this.name = name;
}
public UUID getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//tag::example-identifiers-generators-uuid-implicit[]
}
//end::example-identifiers-generators-uuid-implicit[]

View File

@ -0,0 +1,48 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
*/
package org.hibernate.orm.test.mapping.identifier.uuid.time;
import org.hibernate.id.uuid.CustomVersionOneStrategy;
import org.hibernate.id.uuid.StandardRandomStrategy;
import org.hibernate.orm.test.mapping.identifier.uuid.Helper;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.DomainModelScope;
import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.ServiceRegistryScope;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.Test;
/**
* @author Steve Ebersole
*/
@SuppressWarnings("JUnitMalformedDeclaration")
public class TimeBasedUuidGenerationTests {
@Test
@ServiceRegistry
@DomainModel(annotatedClasses = Book.class)
void verifyModel(ServiceRegistryScope registryScope, DomainModelScope domainModelScope) {
domainModelScope.withHierarchy( Book.class, (descriptor) -> {
Helper.verifyAlgorithm( registryScope, domainModelScope, descriptor, CustomVersionOneStrategy.class );
} );
}
@Test
@ServiceRegistry
@DomainModel(annotatedClasses = Book.class)
@SessionFactory
void testUsage(SessionFactoryScope scope) {
scope.inTransaction( (session) -> {
session.persist( new Book() );
} );
scope.inTransaction( (session) -> {
session.createMutationQuery( "delete Book" ).executeUpdate();
} );
}
}

View File

@ -0,0 +1,54 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
*/
package org.hibernate.orm.test.mapping.identifier.uuid.time2;
import org.hibernate.annotations.UuidGenerator;
import jakarta.persistence.Basic;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import static org.hibernate.annotations.UuidGenerator.Style.TIME;
/**
* @author Steve Ebersole
*/
//tag::example-identifiers-generators-uuid-implicit[]
@Entity
public class Book {
@Id
@GeneratedValue
@UuidGenerator(style = TIME)
private String id;
@Basic
private String name;
//end::example-identifiers-generators-uuid-implicit[]
protected Book() {
// for Hibernate use
}
public Book(String name) {
this.name = name;
}
public String getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//tag::example-identifiers-generators-uuid-implicit[]
}
//end::example-identifiers-generators-uuid-implicit[]

View File

@ -0,0 +1,47 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
*/
package org.hibernate.orm.test.mapping.identifier.uuid.time2;
import org.hibernate.id.uuid.CustomVersionOneStrategy;
import org.hibernate.orm.test.mapping.identifier.uuid.Helper;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.DomainModelScope;
import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.ServiceRegistryScope;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.Test;
/**
* @author Steve Ebersole
*/
@SuppressWarnings("JUnitMalformedDeclaration")
public class TimeBasedUuidGenerationTests {
@Test
@ServiceRegistry
@DomainModel(annotatedClasses = Book.class)
void verifyModel(ServiceRegistryScope registryScope, DomainModelScope domainModelScope) {
domainModelScope.withHierarchy( Book.class, (descriptor) -> {
Helper.verifyAlgorithm( registryScope, domainModelScope, descriptor, CustomVersionOneStrategy.class );
} );
}
@Test
@ServiceRegistry
@DomainModel(annotatedClasses = Book.class)
@SessionFactory
void testUsage(SessionFactoryScope scope) {
scope.inTransaction( (session) -> {
session.persist( new Book() );
} );
scope.inTransaction( (session) -> {
session.createMutationQuery( "delete Book" ).executeUpdate();
} );
}
}

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
*/
package org.hibernate.orm.test.id.uuid.annotation;
package org.hibernate.testing.util.uuid;
import org.hibernate.boot.model.relational.Database;
import org.hibernate.boot.spi.MetadataImplementor;
@ -19,16 +19,29 @@ import org.hibernate.service.ServiceRegistry;
* @author Steve Ebersole
*/
public class IdGeneratorCreationContext implements CustomIdGeneratorCreationContext {
private final ServiceRegistry serviceRegistry;
private final MetadataImplementor domainModel;
private final RootClass entityMapping;
public IdGeneratorCreationContext(MetadataImplementor domainModel, RootClass entityMapping) {
public IdGeneratorCreationContext(
ServiceRegistry serviceRegistry,
MetadataImplementor domainModel,
RootClass entityMapping) {
this.serviceRegistry = serviceRegistry;
this.domainModel = domainModel;
this.entityMapping = entityMapping;
assert entityMapping.getIdentifierProperty() != null;
}
public IdGeneratorCreationContext(MetadataImplementor domainModel, RootClass entityMapping) {
this(
domainModel.getMetadataBuildingOptions().getServiceRegistry(),
domainModel,
entityMapping
);
}
@Override
public IdentifierGeneratorFactory getIdentifierGeneratorFactory() {
return domainModel.getMetadataBuildingOptions().getIdentifierGeneratorFactory();