diff --git a/hibernate-core/src/main/java/org/hibernate/boot/internal/MetadataImpl.java b/hibernate-core/src/main/java/org/hibernate/boot/internal/MetadataImpl.java index eae387206b8f..a89a194c3d55 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/internal/MetadataImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/internal/MetadataImpl.java @@ -66,6 +66,7 @@ import org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator; import org.hibernate.type.spi.TypeConfiguration; +import static java.lang.String.join; import static org.hibernate.cfg.AvailableSettings.EVENT_LISTENER_PREFIX; import static org.hibernate.internal.util.StringHelper.splitAtCommas; import static org.hibernate.internal.util.collections.CollectionHelper.mapOfSize; @@ -164,17 +165,26 @@ public SqmFunctionRegistry getFunctionRegistry() { @Override public SessionFactoryBuilder getSessionFactoryBuilder() { - final SessionFactoryBuilderService factoryBuilderService = metadataBuildingOptions.getServiceRegistry().requireService( SessionFactoryBuilderService.class ); - final SessionFactoryBuilderImplementor defaultBuilder = factoryBuilderService.createSessionFactoryBuilder( this, bootstrapContext ); + final SessionFactoryBuilderImplementor defaultBuilder = + metadataBuildingOptions.getServiceRegistry() + .requireService( SessionFactoryBuilderService.class ) + .createSessionFactoryBuilder( this, bootstrapContext ); + final SessionFactoryBuilder builder = discoverBuilder( defaultBuilder ); + return builder != null ? builder : defaultBuilder; - final ClassLoaderService cls = metadataBuildingOptions.getServiceRegistry().requireService( ClassLoaderService.class ); - final java.util.Collection discoveredBuilderFactories = cls.loadJavaServices( SessionFactoryBuilderFactory.class ); + } + + private SessionFactoryBuilder discoverBuilder(SessionFactoryBuilderImplementor defaultBuilder) { + final java.util.Collection discoveredBuilderFactories = + metadataBuildingOptions.getServiceRegistry().requireService( ClassLoaderService.class ) + .loadJavaServices( SessionFactoryBuilderFactory.class ); SessionFactoryBuilder builder = null; List activeFactoryNames = null; for ( SessionFactoryBuilderFactory discoveredBuilderFactory : discoveredBuilderFactories ) { - final SessionFactoryBuilder returnedBuilder = discoveredBuilderFactory.getSessionFactoryBuilder( this, defaultBuilder ); + final SessionFactoryBuilder returnedBuilder = + discoveredBuilderFactory.getSessionFactoryBuilder( this, defaultBuilder ); if ( returnedBuilder != null ) { if ( activeFactoryNames == null ) { activeFactoryNames = new ArrayList<>(); @@ -186,16 +196,11 @@ public SessionFactoryBuilder getSessionFactoryBuilder() { if ( activeFactoryNames != null && activeFactoryNames.size() > 1 ) { throw new HibernateException( - "Multiple active SessionFactoryBuilderFactory definitions were discovered : " + - String.join(", ", activeFactoryNames) + "Multiple active SessionFactoryBuilderFactory definitions were discovered: " + + join( ", ", activeFactoryNames ) ); } - - if ( builder != null ) { - return builder; - } - - return defaultBuilder; + return builder; } @Override @@ -423,8 +428,7 @@ public void orderColumns(boolean forceOrdering) { } } for ( UserDefinedType userDefinedType : namespace.getUserDefinedTypes() ) { - if ( userDefinedType instanceof UserDefinedObjectType ) { - final UserDefinedObjectType objectType = (UserDefinedObjectType) userDefinedType; + if ( userDefinedType instanceof UserDefinedObjectType objectType ) { if ( objectType.getColumns().size() > 1 ) { final List objectTypeColumns = columnOrderingStrategy.orderUserDefinedTypeColumns( objectType, @@ -440,17 +444,17 @@ public void orderColumns(boolean forceOrdering) { } private boolean shouldOrderTableColumns() { - final ConfigurationService configurationService = metadataBuildingOptions.getServiceRegistry() - .requireService( ConfigurationService.class ); - final Set groupings = SchemaManagementToolCoordinator.ActionGrouping.interpret( - this, - configurationService.getSettings() - ); + final ConfigurationService configurationService = + metadataBuildingOptions.getServiceRegistry().requireService( ConfigurationService.class ); + final Set groupings = + SchemaManagementToolCoordinator.ActionGrouping.interpret( this, + configurationService.getSettings() ); if ( groupings.isEmpty() ) { return false; } for ( SchemaManagementToolCoordinator.ActionGrouping grouping : groupings ) { - if ( isColumnOrderingRelevant( grouping.getScriptAction() ) || isColumnOrderingRelevant( grouping.getDatabaseAction() ) ) { + if ( isColumnOrderingRelevant( grouping.getScriptAction() ) + || isColumnOrderingRelevant( grouping.getDatabaseAction() ) ) { return true; } } @@ -458,14 +462,10 @@ private boolean shouldOrderTableColumns() { } private static boolean isColumnOrderingRelevant(Action grouping) { - switch ( grouping ) { - case CREATE: - case CREATE_DROP: - case CREATE_ONLY: - return true; - default: - return false; - } + return switch ( grouping ) { + case CREATE, CREATE_DROP, CREATE_ONLY -> true; + default -> false; + }; } @Override @@ -489,14 +489,15 @@ public Set getMappedSuperclassMappingsCopy() { @Override public void initSessionFactory(SessionFactoryImplementor sessionFactory) { final ServiceRegistryImplementor sessionFactoryServiceRegistry = sessionFactory.getServiceRegistry(); - assert sessionFactoryServiceRegistry != null; - - final EventListenerRegistry eventListenerRegistry = sessionFactoryServiceRegistry.requireService( EventListenerRegistry.class ); - final ConfigurationService cfgService = sessionFactoryServiceRegistry.requireService( ConfigurationService.class ); - final ClassLoaderService classLoaderService = sessionFactoryServiceRegistry.requireService( ClassLoaderService.class ); - - for ( Map.Entry entry : cfgService.getSettings().entrySet() ) { + final EventListenerRegistry eventListenerRegistry = + sessionFactoryServiceRegistry.requireService( EventListenerRegistry.class ); + final ConfigurationService configurationService = + sessionFactoryServiceRegistry.requireService( ConfigurationService.class ); + final ClassLoaderService classLoaderService = + sessionFactoryServiceRegistry.requireService( ClassLoaderService.class ); + + for ( Map.Entry entry : configurationService.getSettings().entrySet() ) { final String propertyName = entry.getKey(); if ( propertyName.startsWith( EVENT_LISTENER_PREFIX ) ) { final String eventTypeName = propertyName.substring( EVENT_LISTENER_PREFIX.length() + 1 ); @@ -517,8 +518,8 @@ private void appendListeners( @SuppressWarnings("unchecked") T listener = (T) instantiate( listenerImpl, classLoaderService ); if ( !eventType.baseListenerInterface().isInstance( listener ) ) { - throw new HibernateException( "Event listener '" + listenerImpl + "' must implement '" - + eventType.baseListenerInterface().getName() + "'"); + throw new HibernateException( "Event listener '" + listenerImpl + + "' must implement '" + eventType.baseListenerInterface().getName() + "'"); } eventListenerGroup.appendListener( listener ); } @@ -554,7 +555,7 @@ public DiscriminatorType resolveEmbeddableDiscriminatorType( public org.hibernate.type.Type getIdentifierType(String entityName) throws MappingException { final PersistentClass pc = entityBindingMap.get( entityName ); if ( pc == null ) { - throw new MappingException( "persistent class not known: " + entityName ); + throw new MappingException( "Persistent class not known: " + entityName ); } return pc.getIdentifier().getType(); } @@ -563,7 +564,7 @@ public org.hibernate.type.Type getIdentifierType(String entityName) throws Mappi public String getIdentifierPropertyName(String entityName) throws MappingException { final PersistentClass pc = entityBindingMap.get( entityName ); if ( pc == null ) { - throw new MappingException( "persistent class not known: " + entityName ); + throw new MappingException( "Persistent class not known: " + entityName ); } if ( !pc.hasIdentifierProperty() ) { return null; @@ -575,14 +576,11 @@ public String getIdentifierPropertyName(String entityName) throws MappingExcepti public org.hibernate.type.Type getReferencedPropertyType(String entityName, String propertyName) throws MappingException { final PersistentClass pc = entityBindingMap.get( entityName ); if ( pc == null ) { - throw new MappingException( "persistent class not known: " + entityName ); + throw new MappingException( "Persistent class not known: " + entityName ); } - Property prop = pc.getReferencedProperty( propertyName ); + final Property prop = pc.getReferencedProperty( propertyName ); if ( prop == null ) { - throw new MappingException( - "property not known: " + - entityName + '.' + propertyName - ); + throw new MappingException( "Property not known: " + entityName + '.' + propertyName ); } return prop.getType(); } diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/AbstractEntityIdGeneratorResolver.java b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/AbstractEntityIdGeneratorResolver.java index d82d3b1862cf..319a78162f53 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/AbstractEntityIdGeneratorResolver.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/AbstractEntityIdGeneratorResolver.java @@ -137,7 +137,9 @@ protected boolean handleAsMetaAnnotated() { } private Annotation findGeneratorAnnotation(AnnotationTarget annotationTarget) { - final List metaAnnotated = annotationTarget.getMetaAnnotated( IdGeneratorType.class, buildingContext.getMetadataCollector().getSourceModelBuildingContext() ); + final List metaAnnotated = + annotationTarget.getMetaAnnotated( IdGeneratorType.class, + buildingContext.getMetadataCollector().getSourceModelBuildingContext() ); if ( CollectionHelper.size( metaAnnotated ) > 0 ) { return metaAnnotated.get( 0 ); } @@ -149,12 +151,14 @@ protected boolean handleAsLegacyGenerator() { // Handle a few legacy Hibernate generators... final String nameFromGeneratedValue = generatedValue.generator(); if ( !nameFromGeneratedValue.isBlank() ) { - final Class legacyNamedGenerator = mapLegacyNamedGenerator( nameFromGeneratedValue, idValue ); + final Class legacyNamedGenerator = + mapLegacyNamedGenerator( nameFromGeneratedValue, idValue ); if ( legacyNamedGenerator != null ) { final Map configuration = buildLegacyGeneratorConfig(); //noinspection unchecked,rawtypes GeneratorBinder.createGeneratorFrom( - new IdentifierGeneratorDefinition( nameFromGeneratedValue, legacyNamedGenerator.getName(), configuration ), + new IdentifierGeneratorDefinition( nameFromGeneratedValue, + legacyNamedGenerator.getName(), configuration ), idValue, (Map) configuration, buildingContext diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/GeneratorAnnotationHelper.java b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/GeneratorAnnotationHelper.java index 8a47eba3477f..2dc945218bc9 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/GeneratorAnnotationHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/GeneratorAnnotationHelper.java @@ -21,6 +21,7 @@ import org.hibernate.boot.models.HibernateAnnotations; import org.hibernate.boot.registry.classloading.spi.ClassLoadingException; import org.hibernate.boot.spi.MetadataBuildingContext; +import org.hibernate.engine.config.spi.ConfigurationService; import org.hibernate.generator.AnnotationBasedGenerator; import org.hibernate.generator.Generator; import org.hibernate.generator.GeneratorCreationContext; @@ -30,7 +31,6 @@ import org.hibernate.id.PersistentIdentifierGenerator; import org.hibernate.id.enhanced.SequenceStyleGenerator; import org.hibernate.id.uuid.UuidGenerator; -import org.hibernate.internal.util.StringHelper; import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.SimpleValue; import org.hibernate.models.spi.AnnotationDescriptor; @@ -39,15 +39,17 @@ import org.hibernate.models.spi.MemberDetails; import org.hibernate.models.spi.SourceModelBuildingContext; import org.hibernate.models.spi.SourceModelContext; -import org.hibernate.resource.beans.container.spi.BeanContainer; import jakarta.persistence.SequenceGenerator; import jakarta.persistence.TableGenerator; +import static org.hibernate.boot.model.internal.GeneratorBinder.beanContainer; +import static org.hibernate.boot.model.internal.GeneratorBinder.instantiateGenerator; import static org.hibernate.boot.model.internal.GeneratorParameters.collectBaselineProperties; import static org.hibernate.boot.model.internal.GeneratorParameters.fallbackAllocationSize; import static org.hibernate.id.IdentifierGenerator.GENERATOR_NAME; import static org.hibernate.id.OptimizableGenerator.INCREMENT_PARAM; +import static org.hibernate.internal.util.StringHelper.qualifier; import static org.hibernate.internal.util.config.ConfigurationHelper.setIfNotEmpty; /** @@ -62,12 +64,14 @@ public static A findLocalizedMatch( Function nameExtractor, String matchName, MetadataBuildingContext context) { - final SourceModelBuildingContext sourceModelContext = context.getMetadataCollector().getSourceModelBuildingContext(); + final SourceModelBuildingContext sourceModelContext = + context.getMetadataCollector().getSourceModelBuildingContext(); A possibleMatch = null; // first we look on the member - for ( A generatorAnnotation : idMember.getRepeatedAnnotationUsages( generatorAnnotationType, sourceModelContext ) ) { + for ( A generatorAnnotation: + idMember.getRepeatedAnnotationUsages( generatorAnnotationType, sourceModelContext ) ) { if ( nameExtractor != null ) { final String registrationName = nameExtractor.apply( generatorAnnotation ); if ( registrationName.isEmpty() ) { @@ -85,17 +89,16 @@ public static A findLocalizedMatch( } // next, on the class - for ( A generatorAnnotation : idMember.getDeclaringType().getRepeatedAnnotationUsages( generatorAnnotationType, sourceModelContext ) ) { + for ( A generatorAnnotation: + idMember.getDeclaringType().getRepeatedAnnotationUsages( generatorAnnotationType, sourceModelContext ) ) { if ( nameExtractor != null ) { final String registrationName = nameExtractor.apply( generatorAnnotation ); if ( registrationName.isEmpty() ) { if ( possibleMatch == null ) { possibleMatch = generatorAnnotation; } - continue; } - - if ( registrationName.equals( matchName ) ) { + else if ( registrationName.equals( matchName ) ) { return generatorAnnotation; } } @@ -106,19 +109,17 @@ public static A findLocalizedMatch( // lastly, on the package final ClassDetails packageInfo = locatePackageInfoDetails( idMember.getDeclaringType(), context ); - if ( packageInfo != - null ) { - for ( A generatorAnnotation : packageInfo.getRepeatedAnnotationUsages( generatorAnnotationType, sourceModelContext ) ) { + if ( packageInfo != null ) { + for ( A generatorAnnotation: + packageInfo.getRepeatedAnnotationUsages( generatorAnnotationType, sourceModelContext ) ) { if ( nameExtractor != null ) { final String registrationName = nameExtractor.apply( generatorAnnotation ); if ( registrationName.isEmpty() ) { if ( possibleMatch == null ) { possibleMatch = generatorAnnotation; } - continue; } - - if ( registrationName.equals( matchName ) ) { + else if ( registrationName.equals( matchName ) ) { return generatorAnnotation; } } @@ -140,7 +141,7 @@ public static ClassDetails locatePackageInfoDetails(ClassDetails classDetails, S } public static ClassDetails locatePackageInfoDetails(ClassDetails classDetails, ClassDetailsRegistry classDetailsRegistry) { - final String packageInfoFqn = StringHelper.qualifier( classDetails.getName() ) + ".package-info"; + final String packageInfoFqn = qualifier( classDetails.getName() ) + ".package-info"; try { return classDetailsRegistry.resolveClassDetails( packageInfoFqn ); } @@ -156,12 +157,9 @@ public static void handleSequenceGenerator( SimpleValue idValue, MemberDetails idMember, MetadataBuildingContext buildingContext) { - idValue.setCustomIdGeneratorCreator( (creationContext) -> { - final BeanContainer beanContainer = GeneratorBinder.beanContainer( buildingContext ); - final SequenceStyleGenerator identifierGenerator = GeneratorBinder.instantiateGenerator( - beanContainer, - SequenceStyleGenerator.class - ); + idValue.setCustomIdGeneratorCreator( creationContext -> { + final SequenceStyleGenerator identifierGenerator = + instantiateGenerator( beanContainer( buildingContext ), SequenceStyleGenerator.class ); prepareForUse( identifierGenerator, generatorAnnotation, @@ -188,17 +186,14 @@ else if ( nameFromGeneratedValue != null ) { public static void handleTableGenerator( String nameFromGeneratedValue, TableGenerator generatorAnnotation, - PersistentClass entityMapping, SimpleValue idValue, MemberDetails idMember, MetadataBuildingContext buildingContext) { - idValue.setCustomIdGeneratorCreator( (creationContext) -> { - final BeanContainer beanContainer = GeneratorBinder.beanContainer( buildingContext ); - final org.hibernate.id.enhanced.TableGenerator identifierGenerator = GeneratorBinder.instantiateGenerator( - beanContainer, - org.hibernate.id.enhanced.TableGenerator.class - ); - GeneratorAnnotationHelper.prepareForUse( + idValue.setCustomIdGeneratorCreator( creationContext -> { + final org.hibernate.id.enhanced.TableGenerator identifierGenerator = + instantiateGenerator( beanContainer( buildingContext ), + org.hibernate.id.enhanced.TableGenerator.class ); + prepareForUse( identifierGenerator, generatorAnnotation, idMember, @@ -232,14 +227,12 @@ public static void handleIdGeneratorType( SimpleValue idValue, MemberDetails idMember, MetadataBuildingContext buildingContext) { - final IdGeneratorType markerAnnotation = generatorAnnotation.annotationType().getAnnotation( IdGeneratorType.class ); + final IdGeneratorType markerAnnotation = + generatorAnnotation.annotationType().getAnnotation( IdGeneratorType.class ); idValue.setCustomIdGeneratorCreator( (creationContext) -> { - final BeanContainer beanContainer = GeneratorBinder.beanContainer( buildingContext ); - final Generator identifierGenerator = GeneratorBinder.instantiateGenerator( - beanContainer, - markerAnnotation.value() - ); - GeneratorAnnotationHelper.prepareForUse( + final Generator identifierGenerator = + instantiateGenerator( beanContainer( buildingContext ), markerAnnotation.value() ); + prepareForUse( identifierGenerator, generatorAnnotation, idMember, @@ -284,7 +277,8 @@ public static void prepareForUse( : (SimpleValue) creationContext.getPersistentClass().getIdentifierProperty().getValue(), creationContext.getDatabase().getDialect(), creationContext.getRootClass(), - properties::setProperty + properties::setProperty, + creationContext.getServiceRegistry().requireService( ConfigurationService.class ) ); if ( configExtractor != null ) { configExtractor.accept( annotation, properties ); @@ -310,11 +304,11 @@ public static void handleUuidStrategy( null, context ); - idValue.setCustomIdGeneratorCreator( (creationContext) -> new UuidGenerator( generatorConfig, idMember ) ); + idValue.setCustomIdGeneratorCreator( creationContext -> new UuidGenerator( generatorConfig, idMember ) ); } public static void handleIdentityStrategy(SimpleValue idValue) { - idValue.setCustomIdGeneratorCreator( (creationContext) -> new IdentityGenerator() ); + idValue.setCustomIdGeneratorCreator( creationContext -> new IdentityGenerator() ); idValue.setColumnToIdentity(); } @@ -338,7 +332,8 @@ public static void handleGenericGenerator( } GeneratorBinder.createGeneratorFrom( - new IdentifierGeneratorDefinition( generatorName, determineStrategyName( generatorConfig ), configuration ), + new IdentifierGeneratorDefinition( generatorName, + determineStrategyName( generatorConfig ), configuration ), idValue, context ); @@ -346,10 +341,7 @@ public static void handleGenericGenerator( private static String determineStrategyName(GenericGenerator generatorConfig) { final Class type = generatorConfig.type(); - if ( !Objects.equals( type, Generator.class ) ) { - return type.getName(); - } - return generatorConfig.strategy(); + return !Objects.equals( type, Generator.class ) ? type.getName() : generatorConfig.strategy(); } private static void applyAnnotationParameters(GenericGenerator generatorConfig, Map configuration) { 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 d7c99d607bbf..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; @@ -125,7 +127,7 @@ public static void makeIdGenerator( determineImpliedGenerator( strategy, strategyGeneratorClassName, localGenerators ); if ( impliedGenerator != null ) { configuration.putAll( impliedGenerator.getParameters() ); - instantiateGeneratorBean( identifierValue, strategyGeneratorClassName, configuration, context ); + instantiateNamedStrategyGenerator( identifierValue, strategyGeneratorClassName, configuration, context ); return; } } @@ -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; }; @@ -550,9 +567,7 @@ private static G instantiateGenerator( * @param beanContainer an optional {@code BeanContainer} * @param generatorClass a class which implements {@code Generator} */ - public static T instantiateGenerator( - BeanContainer beanContainer, - Class generatorClass) { + public static T instantiateGenerator(BeanContainer beanContainer, Class generatorClass) { return beanContainer != null ? instantiateGeneratorAsBean( beanContainer, generatorClass ) : instantiateGeneratorViaDefaultConstructor( generatorClass ); @@ -612,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 ); } @@ -682,7 +698,7 @@ public static void createGeneratorFrom( Map configuration, MetadataBuildingContext context) { configuration.putAll( defaultedGenerator.getParameters() ); - instantiateGeneratorBean( idValue, defaultedGenerator.getStrategy(), configuration, context ); + instantiateNamedStrategyGenerator( idValue, defaultedGenerator.getStrategy(), configuration, context ); } @@ -690,12 +706,7 @@ public static void createGeneratorFrom( IdentifierGeneratorDefinition defaultedGenerator, SimpleValue idValue, MetadataBuildingContext context) { - createGeneratorFrom( - defaultedGenerator, - idValue, - buildConfigurationMap( idValue ), - context - ); + createGeneratorFrom( defaultedGenerator, idValue, buildConfigurationMap( idValue ), context ); } private static Map buildConfigurationMap(KeyValue idValue) { @@ -760,11 +771,11 @@ private static void setGeneratorCreator( identifierValue.setCustomIdGeneratorCreator( ASSIGNED_IDENTIFIER_GENERATOR_CREATOR ); } else { - instantiateGeneratorBean( identifierValue, generatorStrategy, configuration, context ); + instantiateNamedStrategyGenerator( identifierValue, generatorStrategy, configuration, context ); } } - private static void instantiateGeneratorBean( + private static void instantiateNamedStrategyGenerator( SimpleValue identifierValue, String generatorStrategy, Map configuration, @@ -773,6 +784,8 @@ private static void instantiateGeneratorBean( identifierValue.setCustomIdGeneratorCreator( creationContext -> { final Generator identifierGenerator = instantiateGenerator( beanContainer, generatorClass( generatorStrategy, identifierValue ) ); + // in this code path, there's no generator annotation, + // and therefore no need to call initialize() callConfigure( creationContext, identifierGenerator, configuration, identifierValue ); if ( identifierGenerator instanceof IdentityGenerator) { identifierValue.setColumnToIdentity(); @@ -843,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 9d4f961d28a8..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,30 +80,22 @@ 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 ) ) ); - collectBaselineProperties( identifierValue, dialect, rootClass, parameterCollector ); + collectBaselineProperties( identifierValue, dialect, rootClass, parameterCollector, configService ); } public static int fallbackAllocationSize(Annotation generatorAnnotation, MetadataBuildingContext buildingContext) { if ( generatorAnnotation == null ) { - final ConfigurationService configService = buildingContext - .getBootstrapContext() - .getServiceRegistry() - .requireService( ConfigurationService.class ); + final ConfigurationService configService = buildingContext.getBootstrapContext() + .getServiceRegistry().requireService( ConfigurationService.class ); final String idNamingStrategy = configService.getSetting( ID_DB_STRUCTURE_NAMING_STRATEGY, StandardConverters.STRING ); if ( LegacyNamingStrategy.STRATEGY_NAME.equals( idNamingStrategy ) || LegacyNamingStrategy.class.getName().equals( idNamingStrategy ) @@ -127,18 +108,12 @@ public static int fallbackAllocationSize(Annotation generatorAnnotation, Metadat return OptimizableGenerator.DEFAULT_INCREMENT_SIZE; } - public static void collectBaselineProperties( - SimpleValue identifierValue, + static void collectBaselineProperties( + Value identifierValue, Dialect dialect, RootClass rootClass, - BiConsumer parameterCollector) { - - final ConfigurationService configService = identifierValue - .getMetadata() - .getMetadataBuildingOptions() - .getServiceRegistry() - .requireService( ConfigurationService.class ); - + BiConsumer parameterCollector, + ConfigurationService configService) { //init the table here instead of earlier, so that we can get a quoted table name //TODO: would it be better to simply pass the qualified table name, instead of // splitting it up into schema/catalog/table names @@ -172,7 +147,8 @@ public static void collectBaselineProperties( parameterCollector.accept( IMPLICIT_NAME_BASE, tableName ); } - parameterCollector.accept( CONTRIBUTOR_NAME, identifierValue.getBuildingContext().getCurrentContributorName() ); + parameterCollector.accept( CONTRIBUTOR_NAME, + identifierValue.getBuildingContext().getCurrentContributorName() ); final Map settings = configService.getSettings(); if ( settings.containsKey( AvailableSettings.PREFERRED_POOLED_OPTIMIZER ) ) { @@ -181,7 +157,6 @@ public static void collectBaselineProperties( (String) settings.get( AvailableSettings.PREFERRED_POOLED_OPTIMIZER ) ); } - } public static String identityTablesString(Dialect dialect, RootClass rootClass) { diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/IdBagIdGeneratorResolverSecondPass.java b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/IdBagIdGeneratorResolverSecondPass.java index 202064568cf6..835c1d5177aa 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/IdBagIdGeneratorResolverSecondPass.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/IdBagIdGeneratorResolverSecondPass.java @@ -19,22 +19,23 @@ import org.hibernate.boot.spi.MetadataBuildingContext; import org.hibernate.generator.Generator; import org.hibernate.id.PersistentIdentifierGenerator; -import org.hibernate.id.enhanced.SequenceStyleGenerator; import org.hibernate.mapping.IdentifierBag; import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.SimpleValue; import org.hibernate.models.spi.MemberDetails; -import org.hibernate.resource.beans.container.spi.BeanContainer; import jakarta.persistence.GeneratedValue; import jakarta.persistence.SequenceGenerator; import jakarta.persistence.TableGenerator; +import static org.hibernate.boot.model.internal.GeneratorAnnotationHelper.findLocalizedMatch; +import static org.hibernate.boot.model.internal.GeneratorAnnotationHelper.handleIdentityStrategy; +import static org.hibernate.boot.model.internal.GeneratorAnnotationHelper.handleSequenceGenerator; +import static org.hibernate.boot.model.internal.GeneratorAnnotationHelper.handleTableGenerator; +import static org.hibernate.boot.model.internal.GeneratorAnnotationHelper.handleUuidStrategy; import static org.hibernate.boot.model.internal.GeneratorBinder.createGeneratorFrom; import static org.hibernate.boot.model.internal.GeneratorBinder.makeIdGenerator; -import static org.hibernate.boot.model.internal.GeneratorParameters.fallbackAllocationSize; -import static org.hibernate.id.IdentifierGenerator.GENERATOR_NAME; -import static org.hibernate.id.OptimizableGenerator.INCREMENT_PARAM; +import static org.hibernate.boot.model.internal.GeneratorStrategies.mapLegacyNamedGenerator; /** * IdGeneratorResolver for handling generators assigned to id-bag mappings @@ -63,7 +64,6 @@ public IdBagIdGeneratorResolverSecondPass( this.generatorType = generatorType; this.generatorName = generatorName; this.buildingContext = buildingContext; - this.configuration = new HashMap<>(); } @@ -71,8 +71,8 @@ public IdBagIdGeneratorResolverSecondPass( public void doSecondPass(Map idGeneratorDefinitionMap) throws MappingException { final GeneratedValue generatedValue = idBagMember.getDirectAnnotationUsage( GeneratedValue.class ); switch ( generatedValue.strategy() ) { - case UUID -> GeneratorAnnotationHelper.handleUuidStrategy( idValue, idBagMember, buildingContext ); - case IDENTITY -> GeneratorAnnotationHelper.handleIdentityStrategy( idValue ); + case UUID -> handleUuidStrategy( idValue, idBagMember, buildingContext ); + case IDENTITY -> handleIdentityStrategy( idValue ); case SEQUENCE -> handleSequenceStrategy( generatorName, idValue, @@ -102,10 +102,11 @@ private void handleTableStrategy( MemberDetails idBagMember, MetadataBuildingContext buildingContext) { final InFlightMetadataCollector metadataCollector = buildingContext.getMetadataCollector(); - final GlobalRegistrations globalRegistrations = metadataCollector.getGlobalRegistrations(); final TableGeneratorRegistration globalTableGenerator = - globalRegistrations.getTableGeneratorRegistrations().get( generatorName ); + metadataCollector.getGlobalRegistrations() + .getTableGeneratorRegistrations() + .get( generatorName ); if ( globalTableGenerator != null ) { handleTableGenerator( generatorName, @@ -117,7 +118,7 @@ private void handleTableStrategy( return; } - final TableGenerator localizedTableMatch = GeneratorAnnotationHelper.findLocalizedMatch( + final TableGenerator localizedTableMatch = findLocalizedMatch( JpaAnnotations.TABLE_GENERATOR, idBagMember, TableGenerator::name, @@ -129,10 +130,9 @@ private void handleTableStrategy( return; } - GeneratorAnnotationHelper.handleTableGenerator( + handleTableGenerator( generatorName, new TableGeneratorJpaAnnotation( metadataCollector.getSourceModelBuildingContext() ), - entityMapping, idValue, idBagMember, buildingContext @@ -145,10 +145,11 @@ private void handleSequenceStrategy( MemberDetails idBagMember, MetadataBuildingContext buildingContext) { final InFlightMetadataCollector metadataCollector = buildingContext.getMetadataCollector(); - final GlobalRegistrations globalRegistrations = metadataCollector.getGlobalRegistrations(); final SequenceGeneratorRegistration globalSequenceGenerator = - globalRegistrations.getSequenceGeneratorRegistrations().get( generatorName ); + metadataCollector.getGlobalRegistrations() + .getSequenceGeneratorRegistrations() + .get( generatorName ); if ( globalSequenceGenerator != null ) { handleSequenceGenerator( generatorName, @@ -160,7 +161,7 @@ private void handleSequenceStrategy( return; } - final SequenceGenerator localizedSequencedMatch = GeneratorAnnotationHelper.findLocalizedMatch( + final SequenceGenerator localizedSequencedMatch = findLocalizedMatch( JpaAnnotations.SEQUENCE_GENERATOR, idBagMember, SequenceGenerator::name, @@ -216,8 +217,7 @@ private void handleAutoStrategy( } - final Class legacyNamedGenerator = - GeneratorStrategies.mapLegacyNamedGenerator( generatorName, idValue ); + final Class legacyNamedGenerator = mapLegacyNamedGenerator( generatorName, idValue ); if ( legacyNamedGenerator != null ) { //generator settings if ( idValue.getColumnSpan() == 1 ) { @@ -232,7 +232,7 @@ private void handleAutoStrategy( return; } - final SequenceGenerator localizedSequencedMatch = GeneratorAnnotationHelper.findLocalizedMatch( + final SequenceGenerator localizedSequencedMatch = findLocalizedMatch( JpaAnnotations.SEQUENCE_GENERATOR, idBagMember, SequenceGenerator::name, @@ -244,7 +244,7 @@ private void handleAutoStrategy( return; } - final TableGenerator localizedTableMatch = GeneratorAnnotationHelper.findLocalizedMatch( + final TableGenerator localizedTableMatch = findLocalizedMatch( JpaAnnotations.TABLE_GENERATOR, idBagMember, TableGenerator::name, @@ -258,74 +258,4 @@ private void handleAutoStrategy( makeIdGenerator( idValue, idBagMember, generatorType, generatorName, buildingContext, null ); } - - public static void handleSequenceGenerator( - String nameFromGeneratedValue, - SequenceGenerator generatorAnnotation, - SimpleValue idValue, - MemberDetails idBagMember, - MetadataBuildingContext buildingContext) { - idValue.setCustomIdGeneratorCreator( (creationContext) -> { - final BeanContainer beanContainer = GeneratorBinder.beanContainer( buildingContext ); - final SequenceStyleGenerator identifierGenerator = GeneratorBinder.instantiateGenerator( - beanContainer, - SequenceStyleGenerator.class - ); - GeneratorAnnotationHelper.prepareForUse( - identifierGenerator, - generatorAnnotation, - idBagMember, - properties -> { - if ( generatorAnnotation != null ) { - properties.put( GENERATOR_NAME, generatorAnnotation.name() ); - } - else if ( nameFromGeneratedValue != null ) { - properties.put( GENERATOR_NAME, nameFromGeneratedValue ); - } - // we need to better handle default allocation-size here... - properties.put( INCREMENT_PARAM, fallbackAllocationSize( generatorAnnotation, buildingContext ) ); - }, - generatorAnnotation == null - ? null - : (a, properties) -> SequenceStyleGenerator.applyConfiguration( generatorAnnotation, properties::put ), - creationContext - ); - return identifierGenerator; - } ); - } - - public static void handleTableGenerator( - String nameFromGeneratedValue, - TableGenerator generatorAnnotation, - SimpleValue idValue, - MemberDetails idBagMember, - MetadataBuildingContext buildingContext) { - idValue.setCustomIdGeneratorCreator( (creationContext) -> { - final BeanContainer beanContainer = GeneratorBinder.beanContainer( buildingContext ); - final org.hibernate.id.enhanced.TableGenerator identifierGenerator = GeneratorBinder.instantiateGenerator( - beanContainer, - org.hibernate.id.enhanced.TableGenerator.class - ); - GeneratorAnnotationHelper.prepareForUse( - identifierGenerator, - generatorAnnotation, - idBagMember, - properties -> { - if ( generatorAnnotation != null ) { - properties.put( GENERATOR_NAME, generatorAnnotation.name() ); - } - else if ( nameFromGeneratedValue != null ) { - properties.put( GENERATOR_NAME, nameFromGeneratedValue ); - } - // we need to better handle default allocation-size here... - properties.put( INCREMENT_PARAM, fallbackAllocationSize( generatorAnnotation, buildingContext ) ); - }, - generatorAnnotation == null - ? null - : (a, properties) -> org.hibernate.id.enhanced.TableGenerator.applyConfiguration( generatorAnnotation, properties::put ), - creationContext - ); - return identifierGenerator; - } ); - } } diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/IdGeneratorResolverSecondPass.java b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/IdGeneratorResolverSecondPass.java index bd4964d56be9..adb6cbe47607 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/IdGeneratorResolverSecondPass.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/IdGeneratorResolverSecondPass.java @@ -412,7 +412,6 @@ private void handleTableGenerator(String nameFromGeneratedValue, TableGenerator GeneratorAnnotationHelper.handleTableGenerator( nameFromGeneratedValue, generatorAnnotation, - entityMapping, idValue, idMember, buildingContext 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/boot/model/internal/StrictIdGeneratorResolverSecondPass.java b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/StrictIdGeneratorResolverSecondPass.java index b8c046b82a35..b79d98e376be 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/StrictIdGeneratorResolverSecondPass.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/StrictIdGeneratorResolverSecondPass.java @@ -116,7 +116,6 @@ protected void handleUnnamedTableGenerator() { handleTableGenerator( entityMapping.getJpaEntityName(), globalMatch.configuration(), - entityMapping, idValue, idMember, buildingContext @@ -127,7 +126,6 @@ protected void handleUnnamedTableGenerator() { handleTableGenerator( entityMapping.getJpaEntityName(), new TableGeneratorJpaAnnotation( metadataCollector.getSourceModelBuildingContext() ), - entityMapping, idValue, idMember, buildingContext @@ -145,7 +143,6 @@ protected void handleNamedTableGenerator() { handleTableGenerator( generatedValue.generator(), globalMatch.configuration(), - entityMapping, idValue, idMember, buildingContext @@ -157,7 +154,6 @@ protected void handleNamedTableGenerator() { handleTableGenerator( generatedValue.generator(), new TableGeneratorJpaAnnotation( generatedValue.generator(), metadataCollector.getSourceModelBuildingContext() ), - entityMapping, idValue, idMember, buildingContext @@ -197,7 +193,6 @@ private void handleAutoGenerator(String globalRegistrationName) { handleTableGenerator( globalRegistrationName, globalTableMatch.configuration(), - entityMapping, idValue, idMember, buildingContext diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/ManagedBeanSettings.java b/hibernate-core/src/main/java/org/hibernate/cfg/ManagedBeanSettings.java index d94464530aa3..81e9bda580c7 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/ManagedBeanSettings.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/ManagedBeanSettings.java @@ -50,8 +50,8 @@ public interface ManagedBeanSettings { *

* Note that for CDI-based containers setting this is not necessary - simply * pass the {@link jakarta.enterprise.inject.spi.BeanManager} to use via - * {@link #CDI_BEAN_MANAGER} and optionally specify {@link #DELAY_CDI_ACCESS}. - * This setting useful to integrate non-CDI bean containers such as Spring. + * {@link #JAKARTA_CDI_BEAN_MANAGER} and optionally specify {@link #DELAY_CDI_ACCESS}. + * This setting is useful to integrate non-CDI bean containers such as Spring. * * @since 5.3 */ diff --git a/hibernate-core/src/main/java/org/hibernate/generator/Generator.java b/hibernate-core/src/main/java/org/hibernate/generator/Generator.java index 4dbb61df3b65..254f07b5fb41 100644 --- a/hibernate-core/src/main/java/org/hibernate/generator/Generator.java +++ b/hibernate-core/src/main/java/org/hibernate/generator/Generator.java @@ -49,6 +49,10 @@ *

  • declare a only default constructor, in which case it will not receive parameters. * *

    + * A {@code Generator} may be a managed bean (for example, a CDI bean) instantiated by the + * {@linkplain org.hibernate.resource.beans.container.spi.BeanContainer bean container}. In this + * case, only the first of these options, {@code AnnotationBasedGenerator}, is available. + *

    * A generator must implement {@link #getEventTypes()} to specify the events for which it should be * called to produce a new value. {@link EventTypeSets} provides a convenient list of possibilities. *

    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 03e5ce16e65d..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; @@ -42,7 +42,8 @@ * @author Steve Ebersole */ public class NativeGenerator - implements OnExecutionGenerator, BeforeExecutionGenerator, Configurable, ExportableProducer, AnnotationBasedGenerator { + implements OnExecutionGenerator, BeforeExecutionGenerator, Configurable, ExportableProducer, + AnnotationBasedGenerator { private GenerationType generationType; private org.hibernate.annotations.NativeGenerator annotation; private Generator dialectNativeGenerator; @@ -168,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 ); } diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tuple/internal/AnonymousTupleType.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tuple/internal/AnonymousTupleType.java index 3dbf8f21b607..6da8446da523 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tuple/internal/AnonymousTupleType.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tuple/internal/AnonymousTupleType.java @@ -231,8 +231,7 @@ else if ( sqmType instanceof BasicType ) { @Override public JavaType getExpressibleJavaType() { - //noinspection unchecked - return (JavaType) javaTypeDescriptor; + return javaTypeDescriptor; } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/resource/beans/container/spi/BeanContainer.java b/hibernate-core/src/main/java/org/hibernate/resource/beans/container/spi/BeanContainer.java index 836726dfed7b..df5979120e02 100644 --- a/hibernate-core/src/main/java/org/hibernate/resource/beans/container/spi/BeanContainer.java +++ b/hibernate-core/src/main/java/org/hibernate/resource/beans/container/spi/BeanContainer.java @@ -8,9 +8,14 @@ import org.hibernate.service.spi.Stoppable; /** - * Represents a backend "bean container" - CDI, Spring, etc + * Abstracts any kind of container for managed beans, for example, + * the CDI {@link jakarta.enterprise.inject.spi.BeanManager}. A + * custom bean container may be integrated with Hibernate by + * implementing this interface and specifying the implementation + * using {@value org.hibernate.cfg.AvailableSettings#BEAN_CONTAINER}. * * @see org.hibernate.cfg.AvailableSettings#BEAN_CONTAINER + * @see org.hibernate.resource.beans.container.internal.CdiBasedBeanContainer * * @author Steve Ebersole */ diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/idgen/userdefined/ExportableValueGeneratorTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/idgen/userdefined/ExportableValueGeneratorTest.java new file mode 100644 index 000000000000..5982e627bce2 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/idgen/userdefined/ExportableValueGeneratorTest.java @@ -0,0 +1,103 @@ +/* + * SPDX-License-Identifier: LGPL-2.1-or-later + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.orm.test.idgen.userdefined; + +import jakarta.persistence.Entity; +import jakarta.persistence.EntityManagerFactory; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import org.hibernate.annotations.ValueGenerationType; +import org.hibernate.boot.model.naming.Identifier; +import org.hibernate.boot.model.relational.Database; +import org.hibernate.boot.model.relational.ExportableProducer; +import org.hibernate.boot.model.relational.Sequence; +import org.hibernate.dialect.Dialect; +import org.hibernate.dialect.MySQLDialect; +import org.hibernate.dialect.SybaseASEDialect; +import org.hibernate.generator.EventType; +import org.hibernate.generator.EventTypeSets; +import org.hibernate.generator.OnExecutionGenerator; +import org.hibernate.testing.orm.junit.EntityManagerFactoryScope; +import org.hibernate.testing.orm.junit.Jpa; +import org.hibernate.testing.orm.junit.SkipForDialect; +import org.junit.jupiter.api.Test; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.EnumSet; +import java.util.UUID; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +@Jpa(annotatedClasses = ExportableValueGeneratorTest.WithExportableGenerator.class) +@SkipForDialect( dialectClass = SybaseASEDialect.class ) +@SkipForDialect( dialectClass = MySQLDialect.class) +public class ExportableValueGeneratorTest { + + @Test void test(EntityManagerFactoryScope scope) { + final EntityManagerFactory entityManagerFactory = scope.getEntityManagerFactory(); + final WithExportableGenerator first = new WithExportableGenerator(); + entityManagerFactory.runInTransaction( entityManager -> entityManager.persist( first ) ); + int firstSequenceVal = entityManagerFactory.callInTransaction( entityManager -> + entityManager.find( WithExportableGenerator.class, first.uuid ).sequenceVal ); + assertEquals( 1, firstSequenceVal ); + final WithExportableGenerator second = new WithExportableGenerator(); + entityManagerFactory.runInTransaction( entityManager -> entityManager.persist( second ) ); + int secondSequenceVal = entityManagerFactory.callInTransaction( entityManager -> + entityManager.find( WithExportableGenerator.class, second.uuid ).sequenceVal ); + assertEquals( 2, secondSequenceVal ); + } + + @ValueGenerationType(generatedBy = OnExecutionSequenceGenerator.class) + @Retention(RetentionPolicy.RUNTIME) + @interface OnExecutionSequence { + String sequenceName(); + } + + public static class OnExecutionSequenceGenerator implements OnExecutionGenerator, ExportableProducer { + + final String sequenceName; + + public OnExecutionSequenceGenerator(OnExecutionSequence annotation) { + sequenceName = annotation.sequenceName(); + } + + @Override + public void registerExportables(Database database) { + Identifier testseq = Identifier.toIdentifier( sequenceName ); + database.getDefaultNamespace() + .registerSequence( testseq, + new Sequence( "OnExecutionSequenceGenerator", null, null, testseq ) ); + } + + @Override + public boolean referenceColumnsInSql(Dialect dialect) { + return true; + } + + @Override + public boolean writePropertyValue() { + return false; + } + + @Override + public String[] getReferencedColumnValues(Dialect dialect) { + return new String[] { dialect.getSequenceSupport().getSelectSequenceNextValString( sequenceName ) }; + } + + @Override + public EnumSet getEventTypes() { + return EventTypeSets.INSERT_ONLY; + } + } + + @Entity(name ="WithExportableGenerator") + static class WithExportableGenerator { + @Id @GeneratedValue + UUID uuid; + @OnExecutionSequence(sequenceName = "exported_sequence") + int sequenceVal; + } +}