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; package org.hibernate.annotations;
import org.hibernate.id.IdentifierGenerator;
import java.lang.annotation.Repeatable; import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.Target; 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 * Defines a named identifier generator, an instance of the interface
* {@link org.hibernate.id.IdentifierGenerator}. A named generator may be * {@link org.hibernate.id.IdentifierGenerator}. This allows the use of
* associated with an entity class by: * 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> * <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 * <li>annotating the identifier property of the entity with the JPA-defined
* {@link jakarta.persistence.GeneratedValue @GeneratedValue} annotation, * {@link jakarta.persistence.GeneratedValue @GeneratedValue} annotation,
* and * and
@ -29,10 +37,15 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
* to specify the {@link #name()} of the generator defined using this * to specify the {@link #name()} of the generator defined using this
* annotation. * annotation.
* </ul> * </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: * For example, if we define a generator using:
* <pre>{@code * <pre>{@code
* @GenericGenerator(name = "custom-generator", * @GenericGenerator(name = "custom-generator",
* strategy = "org.hibernate.eg.CustomStringGenerator") * type = org.hibernate.eg.CustomStringGenerator.class)
* }</pre> * }</pre>
* Then we may make use of it by annotating an identifier field as follows: * Then we may make use of it by annotating an identifier field as follows:
* <pre>{@code * <pre>{@code
@ -61,13 +74,18 @@ public @interface GenericGenerator {
*/ */
String name(); 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> * <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}. * <li>a custom class implementing {@link org.hibernate.id.IdentifierGenerator}.
* </ul> * </ul>
*/ */
String strategy(); String strategy() default "native";
/** /**
* Parameters to be passed to {@link org.hibernate.id.IdentifierGenerator#configure} * Parameters to be passed to {@link org.hibernate.id.IdentifierGenerator#configure}
* when the identifier generator is instantiated. * when the identifier generator is instantiated.

View File

@ -481,7 +481,10 @@ public final class AnnotationBinder {
else if ( generatorAnnotation instanceof GenericGenerator ) { else if ( generatorAnnotation instanceof GenericGenerator ) {
final GenericGenerator genericGenerator = (GenericGenerator) generatorAnnotation; final GenericGenerator genericGenerator = (GenericGenerator) generatorAnnotation;
definitionBuilder.setName( genericGenerator.name() ); 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() ) { for ( Parameter parameter : genericGenerator.parameters() ) {
definitionBuilder.addParam( parameter.name(), parameter.value() ); definitionBuilder.addParam( parameter.name(), parameter.value() );
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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