clarify some logic around @GeneratedValue

This commit is contained in:
Gavin 2023-04-11 15:39:59 +02:00 committed by Gavin King
parent 91eb9e1f20
commit c70d9853c7
6 changed files with 68 additions and 77 deletions

View File

@ -95,22 +95,27 @@ public class IdGeneratorInterpreterImpl implements IdGeneratorStrategyInterprete
case TABLE: case TABLE:
return org.hibernate.id.enhanced.TableGenerator.class.getName(); return org.hibernate.id.enhanced.TableGenerator.class.getName();
case AUTO: case AUTO:
if ( "increment".equalsIgnoreCase( context.getGeneratedValueGeneratorName() ) ) { if ( UUID.class.isAssignableFrom( context.getIdType() ) ) {
return IncrementGenerator.class.getName();
}
final Class<?> javaType = context.getIdType();
if ( UUID.class.isAssignableFrom( javaType ) ) {
return UUIDGenerator.class.getName(); return UUIDGenerator.class.getName();
} }
else if ( "increment".equalsIgnoreCase( context.getGeneratedValueGeneratorName() ) ) {
return SequenceStyleGenerator.class.getName(); // special case for @GeneratedValue(name="increment")
// for some reason we consider there to be an implicit
// generator named 'increment' (doesn't seem very useful)
return IncrementGenerator.class.getName();
}
else {
return SequenceStyleGenerator.class.getName();
}
default: default:
// UNKNOWN //case UUID:
// (use the name instead for compatibility with javax.persistence)
if ( "UUID".equals( generationType.name() ) ) { if ( "UUID".equals( generationType.name() ) ) {
return UUIDGenerator.class.getName(); return UUIDGenerator.class.getName();
} }
throw new UnsupportedOperationException( "Unsupported generation type:" + generationType ); else {
throw new UnsupportedOperationException( "Unsupported generation type:" + generationType );
}
} }
} }

View File

@ -13,8 +13,10 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import org.hibernate.AnnotationException;
import org.hibernate.AssertionFailure; import org.hibernate.AssertionFailure;
import org.hibernate.Internal; import org.hibernate.Internal;
import org.hibernate.boot.model.IdGeneratorStrategyInterpreter.GeneratorNameDeterminationContext;
import org.hibernate.id.IdentifierGenerator; import org.hibernate.id.IdentifierGenerator;
import jakarta.persistence.GenerationType; import jakarta.persistence.GenerationType;
@ -109,12 +111,14 @@ public class IdentifierGeneratorDefinition implements Serializable {
return buildTableGeneratorDefinition( name, generationInterpreter ); return buildTableGeneratorDefinition( name, generationInterpreter );
// really AUTO and IDENTITY work the same in this respect, aside from the actual strategy name // really AUTO and IDENTITY work the same in this respect, aside from the actual strategy name
case IDENTITY: case IDENTITY:
strategyName = "identity"; throw new AnnotationException(
break; "@GeneratedValue annotation specified 'strategy=IDENTITY' and 'generator'"
+ " but the generator name is unnecessary"
);
case AUTO: case AUTO:
strategyName = generationInterpreter.determineGeneratorName( strategyName = generationInterpreter.determineGeneratorName(
generationType, generationType,
new IdGeneratorStrategyInterpreter.GeneratorNameDeterminationContext() { new GeneratorNameDeterminationContext() {
@Override @Override
public Class<?> getIdType() { public Class<?> getIdType() {
return idType; return idType;
@ -127,7 +131,17 @@ public class IdentifierGeneratorDefinition implements Serializable {
); );
break; break;
default: default:
throw new AssertionFailure( "unknown generator type: " + generationType ); //case UUID:
// (use the name instead for compatibility with javax.persistence)
if ( "UUID".equals( generationType.name() ) ) {
throw new AnnotationException(
"@GeneratedValue annotation specified 'strategy=UUID' and 'generator'"
+ " but the generator name is unnecessary"
);
}
else {
throw new AssertionFailure( "unknown generator type: " + generationType );
}
} }
return new IdentifierGeneratorDefinition( return new IdentifierGeneratorDefinition(
@ -137,7 +151,8 @@ public class IdentifierGeneratorDefinition implements Serializable {
); );
} }
private static IdentifierGeneratorDefinition buildTableGeneratorDefinition(String name, IdGeneratorStrategyInterpreter generationInterpreter) { private static IdentifierGeneratorDefinition buildTableGeneratorDefinition(
String name, IdGeneratorStrategyInterpreter generationInterpreter) {
final Builder builder = new Builder(); final Builder builder = new Builder();
generationInterpreter.interpretTableGenerator( generationInterpreter.interpretTableGenerator(
new TableGenerator() { new TableGenerator() {
@ -207,7 +222,8 @@ public class IdentifierGeneratorDefinition implements Serializable {
return builder.build(); return builder.build();
} }
private static IdentifierGeneratorDefinition buildSequenceGeneratorDefinition(String name, IdGeneratorStrategyInterpreter generationInterpreter) { private static IdentifierGeneratorDefinition buildSequenceGeneratorDefinition(
String name, IdGeneratorStrategyInterpreter generationInterpreter) {
final Builder builder = new Builder(); final Builder builder = new Builder();
generationInterpreter.interpretSequenceGenerator( generationInterpreter.interpretSequenceGenerator(
new SequenceGenerator() { new SequenceGenerator() {

View File

@ -142,7 +142,7 @@ public class GeneratorBinder {
private static IdentifierGeneratorDefinition makeIdentifierGeneratorDefinition( private static IdentifierGeneratorDefinition makeIdentifierGeneratorDefinition(
String name, String name,
XProperty idXProperty, XProperty idProperty,
Map<String, IdentifierGeneratorDefinition> localGenerators, Map<String, IdentifierGeneratorDefinition> localGenerators,
MetadataBuildingContext buildingContext) { MetadataBuildingContext buildingContext) {
if ( localGenerators != null ) { if ( localGenerators != null ) {
@ -160,7 +160,7 @@ public class GeneratorBinder {
LOG.debugf( "Could not resolve explicit IdentifierGeneratorDefinition - using implicit interpretation (%s)", name ); LOG.debugf( "Could not resolve explicit IdentifierGeneratorDefinition - using implicit interpretation (%s)", name );
final GeneratedValue generatedValue = idXProperty.getAnnotation( GeneratedValue.class ); final GeneratedValue generatedValue = idProperty.getAnnotation( GeneratedValue.class );
if ( generatedValue == null ) { if ( generatedValue == null ) {
// this should really never happen, but it's easy to protect against it... // this should really never happen, but it's easy to protect against it...
return new IdentifierGeneratorDefinition( DEFAULT_ID_GEN_STRATEGY, DEFAULT_ID_GEN_STRATEGY ); return new IdentifierGeneratorDefinition( DEFAULT_ID_GEN_STRATEGY, DEFAULT_ID_GEN_STRATEGY );
@ -171,7 +171,7 @@ public class GeneratorBinder {
buildingContext buildingContext
.getBootstrapContext() .getBootstrapContext()
.getReflectionManager() .getReflectionManager()
.toClass( idXProperty.getType() ), .toClass( idProperty.getType() ),
generatedValue.generator(), generatedValue.generator(),
buildingContext.getBuildingOptions().getIdGenerationTypeInterpreter(), buildingContext.getBuildingOptions().getIdGenerationTypeInterpreter(),
interpretGenerationType( generatedValue ) interpretGenerationType( generatedValue )

View File

@ -40,7 +40,6 @@ import java.util.TimeZone;
import java.util.UUID; import java.util.UUID;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.hibernate.AssertionFailure;
import org.hibernate.Incubating; import org.hibernate.Incubating;
import org.hibernate.Length; import org.hibernate.Length;
import org.hibernate.LockMode; import org.hibernate.LockMode;
@ -1740,35 +1739,12 @@ public abstract class Dialect implements ConversionContext, TypeContributor, Fun
// native identifier generation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // native identifier generation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* The "native" id generation strategy for this dialect.
* <p>
* This is the id generation strategy which should be used when {@code "native"} is
* specified in {@code hbm.xml}, or {@link GenerationType#AUTO} is specified by the
* {@link jakarta.persistence.GeneratedValue#strategy @GeneratedValue} annotation.
*
* @return The native generator strategy.
*/
@Incubating
public GenerationType getNativeIdentifierGenerationType() {
switch ( getNativeIdentifierGeneratorStrategy() ) {
case "identity":
return GenerationType.IDENTITY;
case "sequence":
return GenerationType.SEQUENCE;
case "uuid":
return GenerationType.UUID;
default:
throw new AssertionFailure( "unknown native generation type" );
}
}
/** /**
* The name identifying the "native" id generation strategy for this dialect. * The name identifying the "native" id generation strategy for this dialect.
* <p> * <p>
* This is the id generation strategy which should be used when {@code "native"} is * This is the name of the id generation strategy which should be used when
* specified in {@code hbm.xml}, or {@link GenerationType#AUTO} is specified by the * {@code "native"} is specified in {@code hbm.xml}.
* {@link jakarta.persistence.GeneratedValue#strategy @GeneratedValue} annotation.
* *
* @return The name identifying the native generator strategy. * @return The name identifying the native generator strategy.
*/ */

View File

@ -352,12 +352,6 @@ public class DialectDelegateWrapper extends Dialect {
return wrapped.getLobMergeStrategy(); return wrapped.getLobMergeStrategy();
} }
@Override
@Incubating
public GenerationType getNativeIdentifierGenerationType() {
return wrapped.getNativeIdentifierGenerationType();
}
@Override @Override
public String getNativeIdentifierGeneratorStrategy() { public String getNativeIdentifierGeneratorStrategy() {
return wrapped.getNativeIdentifierGeneratorStrategy(); return wrapped.getNativeIdentifierGeneratorStrategy();

View File

@ -36,7 +36,6 @@ import org.hibernate.id.factory.spi.GenerationTypeStrategy;
import org.hibernate.id.factory.spi.GenerationTypeStrategyRegistration; import org.hibernate.id.factory.spi.GenerationTypeStrategyRegistration;
import org.hibernate.id.factory.spi.GeneratorDefinitionResolver; import org.hibernate.id.factory.spi.GeneratorDefinitionResolver;
import org.hibernate.id.factory.spi.StandardGenerator; import org.hibernate.id.factory.spi.StandardGenerator;
import org.hibernate.internal.log.DeprecationLogger;
import org.hibernate.jpa.spi.IdentifierGeneratorStrategyProvider; import org.hibernate.jpa.spi.IdentifierGeneratorStrategyProvider;
import org.hibernate.resource.beans.container.spi.BeanContainer; import org.hibernate.resource.beans.container.spi.BeanContainer;
import org.hibernate.resource.beans.internal.FallbackBeanInstanceProducer; import org.hibernate.resource.beans.internal.FallbackBeanInstanceProducer;
@ -50,6 +49,7 @@ import jakarta.persistence.GenerationType;
import static org.hibernate.cfg.AvailableSettings.IDENTIFIER_GENERATOR_STRATEGY_PROVIDER; import static org.hibernate.cfg.AvailableSettings.IDENTIFIER_GENERATOR_STRATEGY_PROVIDER;
import static org.hibernate.id.factory.IdGenFactoryLogging.ID_GEN_FAC_LOGGER; import static org.hibernate.id.factory.IdGenFactoryLogging.ID_GEN_FAC_LOGGER;
import static org.hibernate.internal.log.DeprecationLogger.DEPRECATION_LOGGER;
/** /**
* Basic implementation of {@link org.hibernate.id.factory.IdentifierGeneratorFactory}, * Basic implementation of {@link org.hibernate.id.factory.IdentifierGeneratorFactory},
@ -151,7 +151,7 @@ public class StandardIdentifierGeneratorFactory
final ConfigurationService configService = serviceRegistry.getService( ConfigurationService.class ); final ConfigurationService configService = serviceRegistry.getService( ConfigurationService.class );
final Object providerSetting = configService.getSettings().get( IDENTIFIER_GENERATOR_STRATEGY_PROVIDER ); final Object providerSetting = configService.getSettings().get( IDENTIFIER_GENERATOR_STRATEGY_PROVIDER );
if ( providerSetting != null ) { if ( providerSetting != null ) {
DeprecationLogger.DEPRECATION_LOGGER.deprecatedSetting2( DEPRECATION_LOGGER.deprecatedSetting2(
IDENTIFIER_GENERATOR_STRATEGY_PROVIDER, IDENTIFIER_GENERATOR_STRATEGY_PROVIDER,
"supply a org.hibernate.id.factory.spi.GenerationTypeStrategyRegistration Java service" "supply a org.hibernate.id.factory.spi.GenerationTypeStrategyRegistration Java service"
); );
@ -243,32 +243,32 @@ public class StandardIdentifierGeneratorFactory
@Override @Override
public Class<? extends Generator> getIdentifierGeneratorClass(String strategy) { public Class<? extends Generator> getIdentifierGeneratorClass(String strategy) {
if ( "hilo".equals( strategy ) ) { switch ( strategy ) {
throw new UnsupportedOperationException( "Support for 'hilo' generator has been removed" ); case "hilo":
throw new UnsupportedOperationException( "Support for 'hilo' generator has been removed" );
case "native":
strategy = getDialect().getNativeIdentifierGeneratorStrategy();
//then fall through:
default:
Class<? extends Generator> generatorClass = legacyGeneratorClassNameMap.get( strategy );
return generatorClass != null ? generatorClass : generatorClassForName( strategy );
} }
final String resolvedStrategy = "native".equals( strategy ) }
? getDialect().getNativeIdentifierGeneratorStrategy()
: strategy;
Class<? extends Generator> generatorClass = legacyGeneratorClassNameMap.get( resolvedStrategy ); private Class<? extends Generator> generatorClassForName(String strategy) {
if ( generatorClass != null ) { try {
return generatorClass; Class<? extends Generator> clazz =
serviceRegistry.getService( ClassLoaderService.class )
.classForName( strategy );
if ( !Generator.class.isAssignableFrom( clazz ) ) {
// in principle, this shouldn't happen, since @GenericGenerator
// constrains the type to subtypes of Generator
throw new MappingException( clazz.getName() + " does not implement 'Generator'" );
}
return clazz;
} }
else { catch ( ClassLoadingException e ) {
try { throw new MappingException( String.format( "Could not interpret id generator strategy [%s]", strategy) );
Class<? extends Generator> clazz =
serviceRegistry.getService( ClassLoaderService.class )
.classForName( resolvedStrategy );
if ( !Generator.class.isAssignableFrom( clazz ) ) {
// in principle, this shouldn't happen, since @GenericGenerator
// constrains the type to subtypes of Generator
throw new MappingException( clazz.getName() + " does not implement 'Generator'" );
}
return clazz;
}
catch ( ClassLoadingException e ) {
throw new MappingException( String.format( "Could not interpret id generator strategy [%s]", strategy ) );
}
} }
} }
} }