From 35b47c4db716aad588cfb5ec8745518427069b59 Mon Sep 17 00:00:00 2001 From: Gavin King Date: Mon, 23 Dec 2024 10:43:38 +0100 Subject: [PATCH] finish the job of fully-unifying value generators with id generators by letting value generators implement Configurable and ExportableProducer --- .../boot/model/internal/GeneratorBinder.java | 68 ++++++++++++------- .../model/internal/GeneratorParameters.java | 35 +++------- .../boot/model/internal/PropertyBinder.java | 2 +- .../org/hibernate/id/NativeGenerator.java | 11 +-- 4 files changed, 60 insertions(+), 56 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/GeneratorBinder.java b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/GeneratorBinder.java index c06b937f9ffd..fa27b8a1ab74 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/GeneratorBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/GeneratorBinder.java @@ -28,6 +28,7 @@ import org.hibernate.boot.spi.InFlightMetadataCollector; import org.hibernate.boot.spi.MetadataBuildingContext; import org.hibernate.boot.spi.PropertyData; +import org.hibernate.engine.config.spi.ConfigurationService; import org.hibernate.generator.AnnotationBasedGenerator; import org.hibernate.generator.Assigned; import org.hibernate.generator.BeforeExecutionGenerator; @@ -46,6 +47,7 @@ import org.hibernate.mapping.KeyValue; import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.SimpleValue; +import org.hibernate.mapping.Value; import org.hibernate.models.spi.AnnotationTarget; import org.hibernate.models.spi.MemberDetails; import org.hibernate.models.spi.SourceModelBuildingContext; @@ -344,17 +346,11 @@ private static void checkGeneratorClass(Class generatorClas } private static void checkGeneratorInterfaces(Class generatorClass) { - // we don't yet support the additional "fancy" operations of - // IdentifierGenerator with regular generators, though this - // would be extremely easy to add if anyone asks for it + // A regular value generator should not implement legacy IdentifierGenerator if ( IdentifierGenerator.class.isAssignableFrom( generatorClass ) ) { throw new AnnotationException("Generator class '" + generatorClass.getName() + "' implements 'IdentifierGenerator' and may not be used with '@ValueGenerationType'"); } - if ( ExportableProducer.class.isAssignableFrom( generatorClass ) ) { - throw new AnnotationException("Generator class '" + generatorClass.getName() - + "' implements 'ExportableProducer' and may not be used with '@ValueGenerationType'"); - } } /** @@ -363,6 +359,7 @@ private static void checkGeneratorInterfaces(Class generato */ private static GeneratorCreator generatorCreator( MemberDetails memberDetails, + Value value, Annotation annotation, BeanContainer beanContainer) { final Class annotationType = annotation.annotationType(); @@ -372,21 +369,42 @@ private static GeneratorCreator generatorCreator( checkGeneratorClass( generatorClass ); checkGeneratorInterfaces( generatorClass ); return creationContext -> { - final Generator generator = instantiateGenerator( - annotation, - beanContainer, - creationContext, - generatorClass, - memberDetails, - annotationType - ); - callInitialize( annotation, memberDetails, creationContext, generator ); - //TODO: callConfigure( creationContext, generator, emptyMap(), identifierValue ); + final Generator generator = + instantiateAndInitializeGenerator( + value, + annotation, + beanContainer, + creationContext, + generatorClass, + memberDetails, + annotationType + ); checkVersionGenerationAlways( memberDetails, generator ); return generator; }; } + private static Generator instantiateAndInitializeGenerator( + Value value, + Annotation annotation, + BeanContainer beanContainer, + GeneratorCreationContext creationContext, + Class generatorClass, + MemberDetails memberDetails, + Class annotationType) { + final Generator generator = instantiateGenerator( + annotation, + beanContainer, + creationContext, + generatorClass, + memberDetails, + annotationType + ); + callInitialize( annotation, memberDetails, creationContext, generator ); + callConfigure( creationContext, generator, emptyMap(), value ); + return generator; + } + /** * Return a {@link GeneratorCreator} for an id attribute annotated * with an {@linkplain IdGeneratorType id generator annotation}. @@ -403,7 +421,8 @@ private static GeneratorCreator identifierGeneratorCreator( checkGeneratorClass( generatorClass ); return creationContext -> { final Generator generator = - instantiateGenerator( + instantiateAndInitializeGenerator( + identifierValue, annotation, beanContainer, creationContext, @@ -411,8 +430,6 @@ private static GeneratorCreator identifierGeneratorCreator( idAttributeMember, annotationType ); - callInitialize( annotation, idAttributeMember, creationContext, generator ); - callConfigure( creationContext, generator, emptyMap(), identifierValue ); checkIdGeneratorTiming( annotationType, generator ); return generator; }; @@ -610,13 +627,14 @@ public static void callConfigure( GeneratorCreationContext creationContext, Generator generator, Map configuration, - SimpleValue identifierValue) { + Value value) { if ( generator instanceof Configurable configurable ) { final Properties parameters = collectParameters( - identifierValue, + value, creationContext.getDatabase().getDialect(), creationContext.getRootClass(), - configuration + configuration, + creationContext.getServiceRegistry().requireService( ConfigurationService.class ) ); configurable.configure( creationContext, parameters ); } @@ -838,13 +856,13 @@ else if ( idAttributeMember.hasDirectAnnotationUsage( GeneratedValue.class ) ) { */ static GeneratorCreator createValueGeneratorFromAnnotations( PropertyHolder holder, String propertyName, - MemberDetails property, MetadataBuildingContext context) { + Value value, MemberDetails property, MetadataBuildingContext context) { final List generatorAnnotations = property.getMetaAnnotated( ValueGenerationType.class, context.getMetadataCollector().getSourceModelBuildingContext() ); return switch ( generatorAnnotations.size() ) { case 0 -> null; - case 1 -> generatorCreator( property, generatorAnnotations.get(0), beanContainer( context ) ); + case 1 -> generatorCreator( property, value, generatorAnnotations.get(0), beanContainer( context ) ); default -> throw new AnnotationException( "Property '" + qualify( holder.getPath(), propertyName ) + "' has too many generator annotations: " + generatorAnnotations ); }; diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/GeneratorParameters.java b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/GeneratorParameters.java index c4ec7f73ebc8..8623b6400fd1 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/GeneratorParameters.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/GeneratorParameters.java @@ -27,12 +27,12 @@ import org.hibernate.internal.CoreMessageLogger; import org.hibernate.mapping.Column; import org.hibernate.mapping.RootClass; -import org.hibernate.mapping.SimpleValue; import org.hibernate.mapping.Table; import jakarta.persistence.SequenceGenerator; import jakarta.persistence.TableGenerator; import jakarta.persistence.UniqueConstraint; +import org.hibernate.mapping.Value; import static org.hibernate.cfg.MappingSettings.ID_DB_STRUCTURE_NAMING_STRATEGY; import static org.hibernate.id.IdentifierGenerator.CONTRIBUTOR_NAME; @@ -66,24 +66,13 @@ public class GeneratorParameters { * {@link Configurable#configure(GeneratorCreationContext, Properties)}. */ public static Properties collectParameters( - SimpleValue identifierValue, - Dialect dialect, - RootClass rootClass) { - final Properties params = new Properties(); - collectParameters( identifierValue, dialect, rootClass, params::put ); - return params; - } - - /** - * Collect the parameters which should be passed to - * {@link Configurable#configure(GeneratorCreationContext, Properties)}. - */ - public static Properties collectParameters( - SimpleValue identifierValue, + Value identifierValue, Dialect dialect, RootClass rootClass, - Map configuration) { - final Properties params = collectParameters( identifierValue, dialect, rootClass ); + Map configuration, + ConfigurationService configService) { + final Properties params = new Properties(); + collectParameters( identifierValue, dialect, rootClass, params::put, configService ); if ( configuration != null ) { params.putAll( configuration ); } @@ -91,15 +80,11 @@ public static Properties collectParameters( } public static void collectParameters( - SimpleValue identifierValue, + Value identifierValue, Dialect dialect, RootClass rootClass, - BiConsumer parameterCollector) { - - final ConfigurationService configService = - identifierValue.getMetadata().getMetadataBuildingOptions() - .getServiceRegistry().requireService( ConfigurationService.class ); - + BiConsumer parameterCollector, + ConfigurationService configService) { // default initial value and allocation size per-JPA defaults parameterCollector.accept( INITIAL_PARAM, String.valueOf( DEFAULT_INITIAL_VALUE ) ); parameterCollector.accept( INCREMENT_PARAM, String.valueOf( defaultIncrement( configService ) ) ); @@ -124,7 +109,7 @@ public static int fallbackAllocationSize(Annotation generatorAnnotation, Metadat } static void collectBaselineProperties( - SimpleValue identifierValue, + Value identifierValue, Dialect dialect, RootClass rootClass, BiConsumer parameterCollector, diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/PropertyBinder.java b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/PropertyBinder.java index 076392967515..178e8b2f34f7 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/PropertyBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/PropertyBinder.java @@ -450,7 +450,7 @@ public Property makeProperty() { private void handleValueGeneration(Property property) { if ( memberDetails != null ) { property.setValueGeneratorCreator( - createValueGeneratorFromAnnotations( holder, name, memberDetails, buildingContext ) ); + createValueGeneratorFromAnnotations( holder, name, value, memberDetails, buildingContext ) ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/id/NativeGenerator.java b/hibernate-core/src/main/java/org/hibernate/id/NativeGenerator.java index 54bb11f03c77..033107a416a6 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/NativeGenerator.java +++ b/hibernate-core/src/main/java/org/hibernate/id/NativeGenerator.java @@ -6,11 +6,11 @@ import jakarta.persistence.GenerationType; import jakarta.persistence.SequenceGenerator; -import org.hibernate.boot.model.internal.GeneratorParameters; import org.hibernate.boot.model.relational.Database; import org.hibernate.boot.model.relational.ExportableProducer; import org.hibernate.boot.model.relational.SqlStringGenerationContext; import org.hibernate.dialect.Dialect; +import org.hibernate.engine.config.spi.ConfigurationService; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.generator.AnnotationBasedGenerator; import org.hibernate.generator.BeforeExecutionGenerator; @@ -22,7 +22,6 @@ import org.hibernate.id.enhanced.TableGenerator; import org.hibernate.id.insert.InsertGeneratedIdentifierDelegate; import org.hibernate.id.uuid.UuidGenerator; -import org.hibernate.mapping.SimpleValue; import org.hibernate.persister.entity.EntityPersister; import java.lang.reflect.Member; @@ -30,6 +29,7 @@ import java.util.Map; import java.util.Properties; +import static org.hibernate.boot.model.internal.GeneratorParameters.collectParameters; import static org.hibernate.id.IdentifierGenerator.GENERATOR_NAME; import static org.hibernate.id.OptimizableGenerator.INCREMENT_PARAM; @@ -169,11 +169,12 @@ private void applyProperties( private static void applyCommonConfiguration( Map mapRef, GeneratorCreationContext context) { - GeneratorParameters.collectParameters( - (SimpleValue) context.getProperty().getValue(), + collectParameters( + context.getProperty().getValue(), context.getDatabase().getDialect(), context.getRootClass(), - mapRef::put + mapRef::put, + context.getServiceRegistry().requireService( ConfigurationService.class ) ); mapRef.put( INCREMENT_PARAM, 1 ); }