HHH-15781 make @GenericGenerator typesafe by adding type() member

this annotation is not deprecated, so we should at least make it typesafe
This commit is contained in:
Gavin 2022-11-29 22:55:33 +01:00 committed by Gavin King
parent 3bab26739d
commit 8ce2241153
9 changed files with 54 additions and 45 deletions

View File

@ -6,6 +6,8 @@
*/
package org.hibernate.annotations;
import org.hibernate.id.IdentifierGenerator;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
@ -18,10 +20,16 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* Defines a named identifier generator, an instance of the interface
* {@link org.hibernate.id.IdentifierGenerator}. A named generator may be
* associated with an entity class by:
* {@link org.hibernate.id.IdentifierGenerator}. This allows the use of
* custom identifier generation strategies beyond those provided by the
* four basic JPA-defined {@linkplain jakarta.persistence.GenerationType
* generation types}.
* <p>
* A named generator may be associated with an entity class by:
* <ul>
* <li>defining a named generator using this annotation, then
* <li>defining a named generator using this annotation, specifying an
* implementation of {@code IdentifierGenerator} using {@link #type},
* then
* <li>annotating the identifier property of the entity with the JPA-defined
* {@link jakarta.persistence.GeneratedValue @GeneratedValue} annotation,
* and
@ -29,10 +37,15 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
* to specify the {@link #name()} of the generator defined using this
* annotation.
* </ul>
* If neither {@link #type} not {@link #strategy} is specified, Hibernate asks
* {@linkplain org.hibernate.dialect.Dialect#getNativeIdentifierGeneratorStrategy
* the dialect} to decide an appropriate strategy. This is equivalent to using
* {@link jakarta.persistence.GenerationType#AUTO AUTO} in JPA.
* <p>
* For example, if we define a generator using:
* <pre>{@code
* @GenericGenerator(name = "custom-generator",
* strategy = "org.hibernate.eg.CustomStringGenerator")
* type = org.hibernate.eg.CustomStringGenerator.class)
* }</pre>
* Then we may make use of it by annotating an identifier field as follows:
* <pre>{@code
@ -61,13 +74,18 @@ public @interface GenericGenerator {
*/
String name();
/**
* The type of identifier generator, either:
* The type of identifier generator, a class implementing
* {@link org.hibernate.id.IdentifierGenerator}.
*/
Class<? extends IdentifierGenerator> type() default IdentifierGenerator.class;
/**
* The type of identifier generator, the name of either:
* <ul>
* <li>the name of a built-in Hibernate id generator, or
* <li>a built-in Hibernate id generator, or
* <li>a custom class implementing {@link org.hibernate.id.IdentifierGenerator}.
* </ul>
*/
String strategy();
String strategy() default "native";
/**
* Parameters to be passed to {@link org.hibernate.id.IdentifierGenerator#configure}
* when the identifier generator is instantiated.

View File

@ -481,7 +481,10 @@ public final class AnnotationBinder {
else if ( generatorAnnotation instanceof GenericGenerator ) {
final GenericGenerator genericGenerator = (GenericGenerator) generatorAnnotation;
definitionBuilder.setName( genericGenerator.name() );
definitionBuilder.setStrategy( genericGenerator.strategy() );
final String strategy = genericGenerator.type().equals(IdentifierGenerator.class)
? genericGenerator.strategy()
: genericGenerator.type().getName();
definitionBuilder.setStrategy(strategy);
for ( Parameter parameter : genericGenerator.parameters() ) {
definitionBuilder.addParam( parameter.name(), parameter.value() );
}

View File

@ -146,10 +146,9 @@ public class StandardIdentifierGeneratorFactory
AvailableSettings.IDENTIFIER_GENERATOR_STRATEGY_PROVIDER,
"supply a org.hibernate.id.factory.spi.GenerationTypeStrategyRegistration Java service"
);
final IdentifierGeneratorStrategyProvider idGeneratorStrategyProvider = serviceRegistry.getService( StrategySelector.class ).resolveStrategy(
IdentifierGeneratorStrategyProvider.class,
providerSetting
);
final IdentifierGeneratorStrategyProvider idGeneratorStrategyProvider =
serviceRegistry.getService( StrategySelector.class )
.resolveStrategy( IdentifierGeneratorStrategyProvider.class, providerSetting );
for ( Map.Entry<String,Class<?>> entry : idGeneratorStrategyProvider.getStrategies().entrySet() ) {
register( entry.getKey(), (Class) entry.getValue() );
}
@ -238,20 +237,21 @@ public class StandardIdentifierGeneratorFactory
if ( "hilo".equals( strategy ) ) {
throw new UnsupportedOperationException( "Support for 'hilo' generator has been removed" );
}
String resolvedStrategy = "native".equals( strategy )
final String resolvedStrategy = "native".equals( strategy )
? getDialect().getNativeIdentifierGeneratorStrategy()
: strategy;
Class generatorClass = legacyGeneratorClassNameMap.get( resolvedStrategy );
try {
Class<? extends IdentifierGenerator> generatorClass = legacyGeneratorClassNameMap.get( resolvedStrategy );
if ( generatorClass == null ) {
final ClassLoaderService cls = serviceRegistry.getService( ClassLoaderService.class );
generatorClass = cls.classForName( resolvedStrategy );
}
try {
return serviceRegistry.getService( ClassLoaderService.class ).classForName( resolvedStrategy );
}
catch ( ClassLoadingException e ) {
throw new MappingException( String.format( "Could not interpret id generator strategy [%s]", strategy ) );
}
}
else {
return generatorClass;
}
}
}

View File

@ -14,7 +14,6 @@ import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.OneToMany;
@ -27,11 +26,10 @@ import org.hibernate.annotations.GenericGenerator;
* @author Andrew C. Oliver andyspam@osintegrators.com
*/
@Entity
@SuppressWarnings("serial")
public class Bunny implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY, generator = "java5_uuid")
@GenericGenerator(name = "java5_uuid", strategy = "org.hibernate.orm.test.annotations.id.UUIDGenerator")
@GeneratedValue(generator = "java5_uuid")
@GenericGenerator(name = "java5_uuid", type = org.hibernate.orm.test.annotations.id.UUIDGenerator.class)
@Column(name = "id", precision = 128, scale = 0)
private BigDecimal id;

View File

@ -12,7 +12,6 @@ import java.math.BigDecimal;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
@ -27,11 +26,10 @@ import org.hibernate.annotations.GenericGenerator;
* @author Andrew C. Oliver andyspam@osintegrators.com
*/
@Entity
@SuppressWarnings("serial")
public class PointyTooth implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY, generator = "java5_uuid")
@GenericGenerator(name = "java5_uuid", strategy = "org.hibernate.orm.test.annotations.id.UUIDGenerator")
@GeneratedValue(generator = "java5_uuid")
@GenericGenerator(name = "java5_uuid", type = org.hibernate.orm.test.annotations.id.UUIDGenerator.class)
@Column(name = "id", precision = 128, scale = 0)
private BigDecimal id;

View File

@ -12,7 +12,6 @@ import java.math.BigDecimal;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
@ -27,11 +26,10 @@ import org.hibernate.annotations.GenericGenerator;
* @author Andrew C. Oliver andyspam@osintegrators.com
*/
@Entity
@SuppressWarnings("serial")
public class TwinkleToes implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY, generator = "java5_uuid")
@GenericGenerator(name = "java5_uuid", strategy = "org.hibernate.orm.test.annotations.id.UUIDGenerator")
@GeneratedValue(generator = "java5_uuid")
@GenericGenerator(name = "java5_uuid", type = org.hibernate.orm.test.annotations.id.UUIDGenerator.class)
@Column(name = "id", precision = 128, scale = 0)
private BigDecimal id;

View File

@ -14,7 +14,6 @@ import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.OneToMany;
@ -27,11 +26,10 @@ import org.hibernate.annotations.GenericGenerator;
* @author Andrew C. Oliver andyspam@osintegrators.com
*/
@Entity
@SuppressWarnings("serial")
public class Bunny implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY, generator = "java5_uuid")
@GenericGenerator(name = "java5_uuid", strategy = "org.hibernate.orm.test.annotations.id.UUIDGenerator")
@GeneratedValue(generator = "java5_uuid")
@GenericGenerator(name = "java5_uuid", type = org.hibernate.orm.test.annotations.id.UUIDGenerator.class)
@Column(name = "id", precision = 128, scale = 0)
private BigDecimal id;

View File

@ -12,7 +12,6 @@ import java.math.BigDecimal;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
@ -27,11 +26,10 @@ import org.hibernate.annotations.GenericGenerator;
* @author Andrew C. Oliver andyspam@osintegrators.com
*/
@Entity
@SuppressWarnings("serial")
public class PointyTooth implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY, generator = "java5_uuid")
@GenericGenerator(name = "java5_uuid", strategy = "org.hibernate.orm.test.annotations.id.UUIDGenerator")
@GeneratedValue(generator = "java5_uuid")
@GenericGenerator(name = "java5_uuid", type = org.hibernate.orm.test.annotations.id.UUIDGenerator.class)
@Column(name = "id", precision = 128, scale = 0)
private BigDecimal id;

View File

@ -12,7 +12,6 @@ import java.math.BigDecimal;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
@ -27,11 +26,10 @@ import org.hibernate.annotations.GenericGenerator;
* @author Andrew C. Oliver andyspam@osintegrators.com
*/
@Entity
@SuppressWarnings("serial")
public class TwinkleToes implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY, generator = "java5_uuid")
@GenericGenerator(name = "java5_uuid", strategy = "org.hibernate.orm.test.annotations.id.UUIDGenerator")
@GeneratedValue(generator = "java5_uuid")
@GenericGenerator(name = "java5_uuid", type = org.hibernate.orm.test.annotations.id.UUIDGenerator.class)
@Column(name = "id", precision = 128, scale = 0)
private BigDecimal id;