From 1d7ed0e84d248942c36e2cd1a4efd705f4096019 Mon Sep 17 00:00:00 2001 From: Gavin King Date: Thu, 30 May 2024 11:15:03 +0200 Subject: [PATCH] HHH-18139 clean up / reorg of generator binding related code Signed-off-by: Gavin King --- .../GenerationStrategyInterpreter.java | 193 ------- .../model/IdentifierGeneratorDefinition.java | 63 +-- .../boot/model/internal/AnnotationBinder.java | 91 +--- .../boot/model/internal/BinderHelper.java | 60 +-- .../boot/model/internal/CollectionBinder.java | 2 +- .../boot/model/internal/EmbeddableBinder.java | 61 ++- .../boot/model/internal/EntityBinder.java | 26 - .../boot/model/internal/GeneratorBinder.java | 486 +++++++----------- .../model/internal/GeneratorParameters.java | 253 +++++++++ .../model/internal/GeneratorStrategies.java | 116 +++++ .../boot/model/internal/IdBagBinder.java | 3 +- .../IdGeneratorResolverSecondPass.java | 39 +- .../boot/model/internal/PropertyBinder.java | 114 +--- .../boot/model/internal/ToOneBinder.java | 18 +- .../id/IdentifierGeneratorHelper.java | 4 +- .../org/hibernate/id/IncrementGenerator.java | 18 +- .../id/PersistentIdentifierGenerator.java | 3 + .../util/collections/CollectionHelper.java | 1 - ...HiloGeneratorWitZeroIncrementSizeTest.java | 5 - .../enhanced/SequenceStyleConfigUnitTest.java | 5 - 20 files changed, 710 insertions(+), 851 deletions(-) delete mode 100644 hibernate-core/src/main/java/org/hibernate/boot/internal/GenerationStrategyInterpreter.java create mode 100644 hibernate-core/src/main/java/org/hibernate/boot/model/internal/GeneratorParameters.java create mode 100644 hibernate-core/src/main/java/org/hibernate/boot/model/internal/GeneratorStrategies.java diff --git a/hibernate-core/src/main/java/org/hibernate/boot/internal/GenerationStrategyInterpreter.java b/hibernate-core/src/main/java/org/hibernate/boot/internal/GenerationStrategyInterpreter.java deleted file mode 100644 index 7ff5d8dd99..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/boot/internal/GenerationStrategyInterpreter.java +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later. - * See the lgpl.txt file in the root directory or . - */ -package org.hibernate.boot.internal; - -import java.util.UUID; - -import org.hibernate.boot.model.IdentifierGeneratorDefinition; -import org.hibernate.id.IncrementGenerator; -import org.hibernate.id.PersistentIdentifierGenerator; -import org.hibernate.id.UUIDGenerator; -import org.hibernate.id.enhanced.SequenceStyleGenerator; -import org.hibernate.internal.CoreLogging; -import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.internal.util.StringHelper; -import org.hibernate.internal.util.collections.CollectionHelper; - -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.SequenceGenerator; -import jakarta.persistence.TableGenerator; -import jakarta.persistence.UniqueConstraint; - -/** - * Interpretations related to value generators based on the {@linkplain GenerationType strategy/type} - * - * @author Steve Ebersole - */ -public class GenerationStrategyInterpreter { - private static final CoreMessageLogger LOG = CoreLogging.messageLogger( GenerationStrategyInterpreter.class ); - public static final GenerationStrategyInterpreter STRATEGY_INTERPRETER = new GenerationStrategyInterpreter(); - - public interface GeneratorNameDeterminationContext { - /** - * The Java type of the attribute defining the id whose value is to - * be generated. - */ - Class getIdType(); - - /** - * The {@link GeneratedValue#generator()} name. - */ - String getGeneratedValueGeneratorName(); - } - - private GenerationStrategyInterpreter() { - } - - public String determineGeneratorName(GenerationType generationType, GeneratorNameDeterminationContext context) { - switch ( generationType ) { - case IDENTITY: { - return "identity"; - } - case SEQUENCE: { - return SequenceStyleGenerator.class.getName(); - } - case TABLE: { - return org.hibernate.id.enhanced.TableGenerator.class.getName(); - } - case UUID: { - return UUIDGenerator.class.getName(); - } - case AUTO: { - if ( UUID.class.isAssignableFrom( context.getIdType() ) ) { - return UUIDGenerator.class.getName(); - } - else if ( "increment".equalsIgnoreCase( context.getGeneratedValueGeneratorName() ) ) { - // 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: { - throw new UnsupportedOperationException( "Unsupported generation type:" + generationType ); - } - } - } - - public void interpretTableGenerator( - TableGenerator tableGeneratorAnnotation, - IdentifierGeneratorDefinition.Builder definitionBuilder) { - definitionBuilder.setName( tableGeneratorAnnotation.name() ); - definitionBuilder.setStrategy( org.hibernate.id.enhanced.TableGenerator.class.getName() ); - definitionBuilder.addParam( org.hibernate.id.enhanced.TableGenerator.CONFIG_PREFER_SEGMENT_PER_ENTITY, "true" ); - - final String catalog = tableGeneratorAnnotation.catalog(); - if ( StringHelper.isNotEmpty( catalog ) ) { - definitionBuilder.addParam( PersistentIdentifierGenerator.CATALOG, catalog ); - } - - final String schema = tableGeneratorAnnotation.schema(); - if ( StringHelper.isNotEmpty( schema ) ) { - definitionBuilder.addParam( PersistentIdentifierGenerator.SCHEMA, schema ); - } - - final String table = tableGeneratorAnnotation.table(); - if ( StringHelper.isNotEmpty( table ) ) { - definitionBuilder.addParam( org.hibernate.id.enhanced.TableGenerator.TABLE_PARAM, table ); - } - - final String pkColumnName = tableGeneratorAnnotation.pkColumnName(); - if ( StringHelper.isNotEmpty( pkColumnName ) ) { - definitionBuilder.addParam( - org.hibernate.id.enhanced.TableGenerator.SEGMENT_COLUMN_PARAM, - pkColumnName - ); - } - - final String pkColumnValue = tableGeneratorAnnotation.pkColumnValue(); - if ( StringHelper.isNotEmpty( pkColumnValue ) ) { - definitionBuilder.addParam( - org.hibernate.id.enhanced.TableGenerator.SEGMENT_VALUE_PARAM, - pkColumnValue - ); - } - - final String valueColumnName = tableGeneratorAnnotation.valueColumnName(); - if ( StringHelper.isNotEmpty( valueColumnName ) ) { - definitionBuilder.addParam( - org.hibernate.id.enhanced.TableGenerator.VALUE_COLUMN_PARAM, - valueColumnName - ); - } - - final String options = tableGeneratorAnnotation.options(); - if ( StringHelper.isNotEmpty( options ) ) { - definitionBuilder.addParam( - PersistentIdentifierGenerator.OPTIONS, - options - ); - } - - definitionBuilder.addParam( - org.hibernate.id.enhanced.TableGenerator.INCREMENT_PARAM, - String.valueOf( tableGeneratorAnnotation.allocationSize() ) - ); - - // See comment on HHH-4884 wrt initialValue. Basically initialValue is really the stated value + 1 - definitionBuilder.addParam( - org.hibernate.id.enhanced.TableGenerator.INITIAL_PARAM, - String.valueOf( tableGeneratorAnnotation.initialValue() + 1 ) - ); - - // TODO : implement unique-constraint support - final UniqueConstraint[] uniqueConstraints = tableGeneratorAnnotation.uniqueConstraints(); - if ( CollectionHelper.isNotEmpty( uniqueConstraints ) ) { - LOG.ignoringTableGeneratorConstraints( tableGeneratorAnnotation.name() ); - } - } - - public void interpretSequenceGenerator( - SequenceGenerator sequenceGeneratorAnnotation, - IdentifierGeneratorDefinition.Builder definitionBuilder) { - definitionBuilder.setName( sequenceGeneratorAnnotation.name() ); - definitionBuilder.setStrategy( SequenceStyleGenerator.class.getName() ); - - final String catalog = sequenceGeneratorAnnotation.catalog(); - if ( StringHelper.isNotEmpty( catalog ) ) { - definitionBuilder.addParam( PersistentIdentifierGenerator.CATALOG, catalog ); - } - - final String schema = sequenceGeneratorAnnotation.schema(); - if ( StringHelper.isNotEmpty( schema ) ) { - definitionBuilder.addParam( PersistentIdentifierGenerator.SCHEMA, schema ); - } - - final String sequenceName = sequenceGeneratorAnnotation.sequenceName(); - if ( StringHelper.isNotEmpty( sequenceName ) ) { - definitionBuilder.addParam( SequenceStyleGenerator.SEQUENCE_PARAM, sequenceName ); - } - - definitionBuilder.addParam( - SequenceStyleGenerator.INCREMENT_PARAM, - String.valueOf( sequenceGeneratorAnnotation.allocationSize() ) - ); - definitionBuilder.addParam( - SequenceStyleGenerator.INITIAL_PARAM, - String.valueOf( sequenceGeneratorAnnotation.initialValue() ) - ); - - final String options = sequenceGeneratorAnnotation.options(); - if ( StringHelper.isNotEmpty( options ) ) { - definitionBuilder.addParam( PersistentIdentifierGenerator.OPTIONS, options ); - } - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/IdentifierGeneratorDefinition.java b/hibernate-core/src/main/java/org/hibernate/boot/model/IdentifierGeneratorDefinition.java index 495ac7d6ee..dba739f613 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/model/IdentifierGeneratorDefinition.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/model/IdentifierGeneratorDefinition.java @@ -6,26 +6,27 @@ */ package org.hibernate.boot.model; -import java.io.Serializable; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; - +import jakarta.persistence.GenerationType; import org.hibernate.AnnotationException; import org.hibernate.AssertionFailure; import org.hibernate.Internal; -import org.hibernate.boot.internal.GenerationStrategyInterpreter; import org.hibernate.boot.models.annotations.internal.SequenceGeneratorJpaAnnotation; import org.hibernate.boot.models.annotations.internal.TableGeneratorJpaAnnotation; import org.hibernate.id.IdentifierGenerator; import org.hibernate.internal.util.StringHelper; +import org.hibernate.models.spi.TypeDetails; -import jakarta.persistence.GenerationType; +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; import static java.util.Collections.emptyMap; +import static java.util.Collections.singletonMap; import static java.util.Collections.unmodifiableMap; -import static org.hibernate.boot.internal.GenerationStrategyInterpreter.STRATEGY_INTERPRETER; +import static org.hibernate.boot.model.internal.GeneratorParameters.interpretSequenceGenerator; +import static org.hibernate.boot.model.internal.GeneratorParameters.interpretTableGenerator; +import static org.hibernate.boot.model.internal.GeneratorStrategies.generatorStrategy; import static org.hibernate.boot.models.JpaAnnotations.SEQUENCE_GENERATOR; import static org.hibernate.boot.models.JpaAnnotations.TABLE_GENERATOR; import static org.hibernate.internal.util.collections.CollectionHelper.isEmpty; @@ -93,7 +94,7 @@ public class IdentifierGeneratorDefinition implements Serializable { @Internal public static IdentifierGeneratorDefinition createImplicit( String name, - Class idType, + TypeDetails idType, String generatorName, GenerationType generationType) { // If we were unable to locate an actual matching named generator assume @@ -104,49 +105,29 @@ public class IdentifierGeneratorDefinition implements Serializable { } switch ( generationType ) { - case SEQUENCE: { + case SEQUENCE: return buildSequenceGeneratorDefinition( name ); - } - case TABLE: { + case TABLE: return buildTableGeneratorDefinition( name ); - } - case IDENTITY: { + case IDENTITY: throw new AnnotationException( "@GeneratedValue annotation specified 'strategy=IDENTITY' and 'generator'" + " but the generator name is unnecessary" ); - } - case UUID: { + case UUID: throw new AnnotationException( "@GeneratedValue annotation specified 'strategy=UUID' and 'generator'" + " but the generator name is unnecessary" ); - } - case AUTO: { - final String strategyName = STRATEGY_INTERPRETER.determineGeneratorName( - generationType, - new GenerationStrategyInterpreter.GeneratorNameDeterminationContext() { - @Override - public Class getIdType() { - return idType; - } - @Override - public String getGeneratedValueGeneratorName() { - return generatorName; - } - } - ); - + case AUTO: return new IdentifierGeneratorDefinition( name, - strategyName, - Collections.singletonMap( IdentifierGenerator.GENERATOR_NAME, name ) + generatorStrategy( generationType, generatorName, idType ), + singletonMap( IdentifierGenerator.GENERATOR_NAME, name ) ); - } + default: + throw new AssertionFailure( "unknown generator type: " + generationType ); } - - throw new AssertionFailure( "unknown generator type: " + generationType ); - } private static IdentifierGeneratorDefinition buildTableGeneratorDefinition(String name) { @@ -155,7 +136,7 @@ public class IdentifierGeneratorDefinition implements Serializable { if ( StringHelper.isNotEmpty( name ) ) { tableGeneratorUsage.name( name ); } - STRATEGY_INTERPRETER.interpretTableGenerator( tableGeneratorUsage, builder ); + interpretTableGenerator( tableGeneratorUsage, builder ); return builder.build(); } @@ -165,7 +146,7 @@ public class IdentifierGeneratorDefinition implements Serializable { if ( StringHelper.isNotEmpty( name ) ) { sequenceGeneratorUsage.name( name ); } - STRATEGY_INTERPRETER.interpretSequenceGenerator( sequenceGeneratorUsage, builder ); + interpretSequenceGenerator( sequenceGeneratorUsage, builder ); return builder.build(); } diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/AnnotationBinder.java b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/AnnotationBinder.java index d2374042a4..eca5c01d55 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/AnnotationBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/AnnotationBinder.java @@ -19,12 +19,10 @@ import org.hibernate.annotations.EmbeddableInstantiatorRegistration; import org.hibernate.annotations.FetchMode; import org.hibernate.annotations.FetchProfile; import org.hibernate.annotations.FetchProfile.FetchOverride; -import org.hibernate.annotations.GenericGenerator; import org.hibernate.annotations.Imported; import org.hibernate.annotations.JavaTypeRegistration; import org.hibernate.annotations.JdbcTypeRegistration; import org.hibernate.annotations.TypeRegistration; -import org.hibernate.boot.internal.GenerationStrategyInterpreter; import org.hibernate.boot.model.IdentifierGeneratorDefinition; import org.hibernate.boot.model.convert.spi.RegisteredConversion; import org.hibernate.boot.models.HibernateAnnotations; @@ -46,15 +44,14 @@ import jakarta.persistence.FetchType; import jakarta.persistence.Inheritance; import jakarta.persistence.InheritanceType; import jakarta.persistence.MappedSuperclass; -import jakarta.persistence.SequenceGenerator; import jakarta.persistence.Table; -import jakarta.persistence.TableGenerator; import static org.hibernate.boot.model.internal.AnnotatedClassType.EMBEDDABLE; import static org.hibernate.boot.model.internal.AnnotatedClassType.ENTITY; import static org.hibernate.boot.model.internal.FilterDefBinder.bindFilterDefs; import static org.hibernate.boot.model.internal.GeneratorBinder.buildGenerators; -import static org.hibernate.boot.model.internal.GeneratorBinder.buildIdGenerator; +import static org.hibernate.boot.model.internal.GeneratorParameters.interpretSequenceGenerator; +import static org.hibernate.boot.model.internal.GeneratorParameters.interpretTableGenerator; import static org.hibernate.boot.model.internal.InheritanceState.getInheritanceStateOfSuperEntity; import static org.hibernate.boot.model.internal.InheritanceState.getSuperclassInheritanceState; import static org.hibernate.internal.CoreLogging.messageLogger; @@ -82,10 +79,7 @@ public final class AnnotationBinder { globalRegistrations.getSequenceGeneratorRegistrations().forEach( (name, generatorRegistration) -> { final IdentifierGeneratorDefinition.Builder definitionBuilder = new IdentifierGeneratorDefinition.Builder(); - GenerationStrategyInterpreter.STRATEGY_INTERPRETER.interpretSequenceGenerator( - generatorRegistration.configuration(), - definitionBuilder - ); + interpretSequenceGenerator( generatorRegistration.configuration(), definitionBuilder ); final IdentifierGeneratorDefinition idGenDef = definitionBuilder.build(); if ( LOG.isTraceEnabled() ) { LOG.tracef( "Adding global sequence generator with name: %s", name ); @@ -95,10 +89,7 @@ public final class AnnotationBinder { globalRegistrations.getTableGeneratorRegistrations().forEach( (name, generatorRegistration) -> { final IdentifierGeneratorDefinition.Builder definitionBuilder = new IdentifierGeneratorDefinition.Builder(); - GenerationStrategyInterpreter.STRATEGY_INTERPRETER.interpretTableGenerator( - generatorRegistration.configuration(), - definitionBuilder - ); + interpretTableGenerator( generatorRegistration.configuration(), definitionBuilder ); final IdentifierGeneratorDefinition idGenDef = definitionBuilder.build(); if ( LOG.isTraceEnabled() ) { LOG.tracef( "Adding global table generator with name: %s", name ); @@ -128,17 +119,20 @@ public final class AnnotationBinder { } ); } + private static SourceModelBuildingContext sourceContext(MetadataBuildingContext context) { + return context.getMetadataCollector().getSourceModelBuildingContext(); + } + public static void bindPackage(ClassLoaderService cls, String packageName, MetadataBuildingContext context) { final Package pack = cls.packageForNameOrNull( packageName ); if ( pack == null ) { return; } - final ClassDetails packageInfoClassDetails = context.getMetadataCollector() - .getSourceModelBuildingContext() - .getClassDetailsRegistry() - .resolveClassDetails( pack.getName() + ".package-info" ); + final ClassDetails packageInfoClassDetails = + sourceContext( context ).getClassDetailsRegistry() + .resolveClassDetails( pack.getName() + ".package-info" ); - handleIdGenerators( packageInfoClassDetails, context ); + buildGenerators( packageInfoClassDetails, context ); bindTypeDescriptorRegistrations( packageInfoClassDetails, context ); bindEmbeddableInstantiatorRegistrations( packageInfoClassDetails, context ); @@ -146,50 +140,17 @@ public final class AnnotationBinder { bindCompositeUserTypeRegistrations( packageInfoClassDetails, context ); bindConverterRegistrations( packageInfoClassDetails, context ); - bindGenericGenerators( packageInfoClassDetails, context ); bindQueries( packageInfoClassDetails, context ); bindFilterDefs( packageInfoClassDetails, context ); } - private static void handleIdGenerators(ClassDetails packageInfoClassDetails, MetadataBuildingContext context) { - final SourceModelBuildingContext sourceModelContext = context.getMetadataCollector().getSourceModelBuildingContext(); - - packageInfoClassDetails.forEachAnnotationUsage( SequenceGenerator.class, sourceModelContext, (usage) -> { - IdentifierGeneratorDefinition idGen = buildIdGenerator( usage, context ); - context.getMetadataCollector().addIdentifierGenerator( idGen ); - if ( LOG.isTraceEnabled() ) { - LOG.tracev( "Add sequence generator with name: {0}", idGen.getName() ); - } - } ); - - packageInfoClassDetails.forEachAnnotationUsage( TableGenerator.class, sourceModelContext, (usage) -> { - IdentifierGeneratorDefinition idGen = buildIdGenerator( usage, context ); - context.getMetadataCollector().addIdentifierGenerator( idGen ); - if ( LOG.isTraceEnabled() ) { - LOG.tracev( "Add table generator with name: {0}", idGen.getName() ); - } - } ); - } - - private static void bindGenericGenerators(AnnotationTarget annotatedElement, MetadataBuildingContext context) { - final SourceModelBuildingContext sourceModelContext = context.getMetadataCollector().getSourceModelBuildingContext(); - - annotatedElement.forEachAnnotationUsage( GenericGenerator.class, sourceModelContext, (usage) -> { - bindGenericGenerator( usage, context ); - } ); - } - - private static void bindGenericGenerator(GenericGenerator def, MetadataBuildingContext context) { - context.getMetadataCollector().addIdentifierGenerator( buildIdGenerator( def, context ) ); - } - public static void bindQueries(AnnotationTarget annotationTarget, MetadataBuildingContext context) { bindNamedJpaQueries( annotationTarget, context ); bindNamedHibernateQueries( annotationTarget, context ); } private static void bindNamedHibernateQueries(AnnotationTarget annotationTarget, MetadataBuildingContext context) { - final SourceModelBuildingContext sourceModelContext = context.getMetadataCollector().getSourceModelBuildingContext(); + final SourceModelBuildingContext sourceModelContext = sourceContext( context ); annotationTarget.forEachRepeatedAnnotationUsages( HibernateAnnotations.NAMED_QUERY, @@ -205,7 +166,7 @@ public final class AnnotationBinder { } private static void bindNamedJpaQueries(AnnotationTarget annotationTarget, MetadataBuildingContext context) { - final SourceModelBuildingContext sourceModelContext = context.getMetadataCollector().getSourceModelBuildingContext(); + final SourceModelBuildingContext sourceModelContext = sourceContext( context ); annotationTarget.forEachRepeatedAnnotationUsages( JpaAnnotations.SQL_RESULT_SET_MAPPING, @@ -293,11 +254,12 @@ public final class AnnotationBinder { private static void bindTypeDescriptorRegistrations( AnnotationTarget annotatedElement, MetadataBuildingContext context) { - final ManagedBeanRegistry managedBeanRegistry = context.getBootstrapContext() - .getServiceRegistry() - .getService( ManagedBeanRegistry.class ); + final ManagedBeanRegistry managedBeanRegistry = + context.getBootstrapContext().getServiceRegistry() + .getService( ManagedBeanRegistry.class ); + + final SourceModelBuildingContext sourceModelContext = sourceContext( context ); - final SourceModelBuildingContext sourceModelContext = context.getMetadataCollector().getSourceModelBuildingContext(); annotatedElement.forEachAnnotationUsage( JavaTypeRegistration.class, sourceModelContext, (usage) -> { handleJavaTypeRegistration( context, managedBeanRegistry, usage ); } ); @@ -343,8 +305,7 @@ public final class AnnotationBinder { private static void bindEmbeddableInstantiatorRegistrations( AnnotationTarget annotatedElement, MetadataBuildingContext context) { - final SourceModelBuildingContext sourceModelContext = context.getMetadataCollector().getSourceModelBuildingContext(); - annotatedElement.forEachAnnotationUsage( EmbeddableInstantiatorRegistration.class, sourceModelContext, (usage) -> { + annotatedElement.forEachAnnotationUsage( EmbeddableInstantiatorRegistration.class, sourceContext( context ), (usage) -> { handleEmbeddableInstantiatorRegistration( context, usage ); } ); } @@ -361,9 +322,7 @@ public final class AnnotationBinder { private static void bindCompositeUserTypeRegistrations( AnnotationTarget annotatedElement, MetadataBuildingContext context) { - final SourceModelBuildingContext sourceModelContext = context.getMetadataCollector().getSourceModelBuildingContext(); - - annotatedElement.forEachAnnotationUsage( CompositeTypeRegistration.class, sourceModelContext, (usage) -> { + annotatedElement.forEachAnnotationUsage( CompositeTypeRegistration.class, sourceContext( context ), (usage) -> { handleCompositeUserTypeRegistration( context, usage ); } ); } @@ -371,8 +330,7 @@ public final class AnnotationBinder { private static void bindUserTypeRegistrations( AnnotationTarget annotatedElement, MetadataBuildingContext context) { - final SourceModelBuildingContext sourceModelContext = context.getMetadataCollector().getSourceModelBuildingContext(); - annotatedElement.forEachAnnotationUsage( TypeRegistration.class, sourceModelContext, (usage) -> { + annotatedElement.forEachAnnotationUsage( TypeRegistration.class, sourceContext( context ), (usage) -> { handleUserTypeRegistration( context, usage ); } ); } @@ -400,7 +358,7 @@ public final class AnnotationBinder { } private static void bindConverterRegistrations(AnnotationTarget container, MetadataBuildingContext context) { - final SourceModelBuildingContext sourceModelContext = context.getMetadataCollector().getSourceModelBuildingContext(); + final SourceModelBuildingContext sourceModelContext = sourceContext( context ); container.forEachAnnotationUsage( ConverterRegistration.class, sourceModelContext, (usage) -> { handleConverterRegistration( usage, context ); } ); @@ -430,8 +388,7 @@ public final class AnnotationBinder { } private static void bindFetchProfiles(AnnotationTarget annotatedElement, MetadataBuildingContext context) { - final SourceModelBuildingContext sourceModelContext = context.getMetadataCollector().getSourceModelBuildingContext(); - annotatedElement.forEachAnnotationUsage( FetchProfile.class, sourceModelContext, (usage) -> { + annotatedElement.forEachAnnotationUsage( FetchProfile.class, sourceContext( context ), (usage) -> { bindFetchProfile( usage, context ); } ); } diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/BinderHelper.java b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/BinderHelper.java index f4ef045326..a8a160962e 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/BinderHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/BinderHelper.java @@ -58,7 +58,6 @@ import org.hibernate.models.spi.ClassDetailsRegistry; import org.hibernate.models.spi.MemberDetails; import org.hibernate.models.spi.SourceModelBuildingContext; import org.hibernate.models.spi.TypeDetails; -import org.hibernate.models.spi.TypeDetailsHelper; import org.hibernate.type.descriptor.java.JavaType; import jakarta.persistence.ConstraintMode; @@ -76,6 +75,7 @@ import static org.hibernate.internal.util.StringHelper.isEmpty; import static org.hibernate.internal.util.StringHelper.isNotEmpty; import static org.hibernate.internal.util.StringHelper.qualifier; import static org.hibernate.internal.util.StringHelper.qualify; +import static org.hibernate.models.spi.TypeDetailsHelper.resolveRawClass; import static org.hibernate.property.access.spi.BuiltInPropertyAccessStrategies.EMBEDDED; import static org.hibernate.property.access.spi.BuiltInPropertyAccessStrategies.NOOP; import static org.hibernate.property.access.spi.BuiltInPropertyAccessStrategies.interpret; @@ -586,8 +586,8 @@ public class BinderHelper { */ public static Property findPropertyByName(PersistentClass associatedClass, String propertyName) { Property property = null; - Property idProperty = associatedClass.getIdentifierProperty(); - String idName = idProperty == null ? null : idProperty.getName(); + final Property idProperty = associatedClass.getIdentifierProperty(); + final String idName = idProperty == null ? null : idProperty.getName(); try { if ( isEmpty( propertyName ) || propertyName.equals( idName ) ) { //default to id @@ -598,9 +598,9 @@ public class BinderHelper { property = idProperty; propertyName = propertyName.substring( idName.length() + 1 ); } - StringTokenizer st = new StringTokenizer( propertyName, ".", false ); - while ( st.hasMoreElements() ) { - String element = (String) st.nextElement(); + final StringTokenizer tokens = new StringTokenizer( propertyName, ".", false ); + while ( tokens.hasMoreElements() ) { + String element = (String) tokens.nextElement(); if ( property == null ) { property = associatedClass.getProperty( element ); } @@ -619,9 +619,9 @@ public class BinderHelper { if ( associatedClass.getIdentifierMapper() == null ) { return null; } - StringTokenizer st = new StringTokenizer( propertyName, ".", false ); - while ( st.hasMoreElements() ) { - String element = (String) st.nextElement(); + final StringTokenizer tokens = new StringTokenizer( propertyName, ".", false ); + while ( tokens.hasMoreElements() ) { + final String element = (String) tokens.nextElement(); if ( property == null ) { property = associatedClass.getIdentifierMapper().getProperty( element ); } @@ -646,15 +646,14 @@ public class BinderHelper { public static Property findPropertyByName(Component component, String propertyName) { Property property = null; try { - if ( propertyName == null - || propertyName.length() == 0) { + if ( isEmpty( propertyName ) ) { // Do not expect to use a primary key for this case return null; } else { - StringTokenizer st = new StringTokenizer( propertyName, ".", false ); - while ( st.hasMoreElements() ) { - String element = (String) st.nextElement(); + final StringTokenizer tokens = new StringTokenizer( propertyName, ".", false ); + while ( tokens.hasMoreElements() ) { + final String element = (String) tokens.nextElement(); if ( property == null ) { property = component.getProperty( element ); } @@ -673,9 +672,9 @@ public class BinderHelper { if ( component.getOwner().getIdentifierMapper() == null ) { return null; } - StringTokenizer st = new StringTokenizer( propertyName, ".", false ); - while ( st.hasMoreElements() ) { - String element = (String) st.nextElement(); + final StringTokenizer tokens = new StringTokenizer( propertyName, ".", false ); + while ( tokens.hasMoreElements() ) { + final String element = (String) tokens.nextElement(); if ( property == null ) { property = component.getOwner().getIdentifierMapper().getProperty( element ); } @@ -834,14 +833,16 @@ public class BinderHelper { MemberDetails property, Consumer consumer, SourceModelBuildingContext sourceModelContext) { - final AnyDiscriminatorValues valuesAnn = property.locateAnnotationUsage( AnyDiscriminatorValues.class, sourceModelContext ); + final AnyDiscriminatorValues valuesAnn = + property.locateAnnotationUsage( AnyDiscriminatorValues.class, sourceModelContext ); if ( valuesAnn != null ) { final AnyDiscriminatorValue[] nestedList = valuesAnn.value(); ArrayHelper.forEach( nestedList, consumer ); return; } - final AnyDiscriminatorValue valueAnn = property.locateAnnotationUsage( AnyDiscriminatorValue.class, sourceModelContext ); + final AnyDiscriminatorValue valueAnn = + property.locateAnnotationUsage( AnyDiscriminatorValue.class, sourceModelContext ); if ( valueAnn != null ) { consumer.accept( valueAnn ); } @@ -957,10 +958,10 @@ public class BinderHelper { return renderCascadeTypeList( cascadeTypes ); } - private static EnumSet convertToHibernateCascadeType(jakarta.persistence.CascadeType[] ejbCascades) { + private static EnumSet convertToHibernateCascadeType(jakarta.persistence.CascadeType[] cascades) { final EnumSet cascadeTypes = EnumSet.noneOf( CascadeType.class ); - if ( ejbCascades != null ) { - for ( jakarta.persistence.CascadeType cascade: ejbCascades ) { + if ( cascades != null ) { + for ( jakarta.persistence.CascadeType cascade: cascades ) { cascadeTypes.add( convertCascadeType( cascade ) ); } } @@ -1028,7 +1029,7 @@ public class BinderHelper { break; } } - return cascade.length() > 0 ? cascade.substring( 1 ) : "none"; + return cascade.isEmpty() ? "none" : cascade.substring(1); } private static void warnAboutDeprecatedCascadeType(CascadeType cascadeType) { @@ -1053,18 +1054,17 @@ public class BinderHelper { return context.getBootstrapContext().getJpaCompliance().isGlobalGeneratorScopeEnabled(); } - static boolean isCompositeId(ClassDetails entityClass, MemberDetails idProperty) { - return entityClass.hasDirectAnnotationUsage( Embeddable.class ) + static boolean isCompositeId(ClassDetails idClass, MemberDetails idProperty) { + return idClass.hasDirectAnnotationUsage( Embeddable.class ) || idProperty.hasDirectAnnotationUsage( EmbeddedId.class ); } - public static boolean isDefault(ClassDetails clazz, MetadataBuildingContext context) { + public static boolean isDefault(ClassDetails clazz) { return clazz == ClassDetails.VOID_CLASS_DETAILS; } - public static boolean isDefault(TypeDetails clazz, MetadataBuildingContext context) { - final ClassDetails rawClassDetails = TypeDetailsHelper.resolveRawClass( clazz ); - return rawClassDetails == ClassDetails.VOID_CLASS_DETAILS; + public static boolean isDefault(TypeDetails clazz) { + return resolveRawClass( clazz ) == ClassDetails.VOID_CLASS_DETAILS; } public static void checkMappedByType( @@ -1121,7 +1121,7 @@ public class BinderHelper { else { final ConstraintMode mode = foreignKey.value(); return mode == NO_CONSTRAINT - || mode == PROVIDER_DEFAULT && noConstraintByDefault; + || mode == PROVIDER_DEFAULT && noConstraintByDefault; } } diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/CollectionBinder.java b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/CollectionBinder.java index 09b835ecb2..de891afc16 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/CollectionBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/CollectionBinder.java @@ -1614,7 +1614,7 @@ public abstract class CollectionBinder { } TypeDetails getElementType() { - if ( isDefault( targetEntity, buildingContext ) ) { + if ( isDefault( targetEntity ) ) { if ( collectionElementType != null ) { return collectionElementType; } diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/EmbeddableBinder.java b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/EmbeddableBinder.java index 5e1c5e65e8..c3a1337e4c 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/EmbeddableBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/EmbeddableBinder.java @@ -6,15 +6,20 @@ */ package org.hibernate.boot.model.internal; -import java.lang.annotation.Annotation; -import java.lang.reflect.Constructor; -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.TreeMap; - +import jakarta.persistence.Column; +import jakarta.persistence.Convert; +import jakarta.persistence.DiscriminatorColumn; +import jakarta.persistence.DiscriminatorValue; +import jakarta.persistence.Embeddable; +import jakarta.persistence.Embedded; +import jakarta.persistence.EmbeddedId; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.ManyToMany; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.MappedSuperclass; +import jakarta.persistence.OneToMany; +import jakarta.persistence.OneToOne; import org.hibernate.AnnotationException; import org.hibernate.annotations.DiscriminatorFormula; import org.hibernate.annotations.Instantiator; @@ -46,32 +51,26 @@ import org.hibernate.resource.beans.spi.ManagedBeanRegistry; import org.hibernate.type.BasicType; import org.hibernate.usertype.CompositeUserType; -import jakarta.persistence.Column; -import jakarta.persistence.Convert; -import jakarta.persistence.DiscriminatorColumn; -import jakarta.persistence.DiscriminatorValue; -import jakarta.persistence.Embeddable; -import jakarta.persistence.Embedded; -import jakarta.persistence.EmbeddedId; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.Id; -import jakarta.persistence.ManyToMany; -import jakarta.persistence.ManyToOne; -import jakarta.persistence.MappedSuperclass; -import jakarta.persistence.OneToMany; -import jakarta.persistence.OneToOne; +import java.lang.annotation.Annotation; +import java.lang.reflect.Constructor; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; import static org.hibernate.boot.model.internal.AnnotatedDiscriminatorColumn.DEFAULT_DISCRIMINATOR_COLUMN_NAME; import static org.hibernate.boot.model.internal.AnnotatedDiscriminatorColumn.buildDiscriminatorColumn; -import static org.hibernate.boot.model.internal.DialectOverridesAnnotationHelper.getOverridableAnnotation; import static org.hibernate.boot.model.internal.BinderHelper.getPath; import static org.hibernate.boot.model.internal.BinderHelper.getPropertyOverriddenByMapperOrMapsId; import static org.hibernate.boot.model.internal.BinderHelper.getRelativePath; import static org.hibernate.boot.model.internal.BinderHelper.hasToOneAnnotation; import static org.hibernate.boot.model.internal.BinderHelper.isGlobalGeneratorNameGlobal; +import static org.hibernate.boot.model.internal.DialectOverridesAnnotationHelper.getOverridableAnnotation; import static org.hibernate.boot.model.internal.GeneratorBinder.buildGenerators; -import static org.hibernate.boot.model.internal.GeneratorBinder.generatorType; import static org.hibernate.boot.model.internal.GeneratorBinder.makeIdGenerator; +import static org.hibernate.boot.model.internal.GeneratorStrategies.generatorStrategy; import static org.hibernate.boot.model.internal.PropertyBinder.addElementsOfClass; import static org.hibernate.boot.model.internal.PropertyBinder.processElementAnnotations; import static org.hibernate.boot.model.internal.PropertyHolderBuilder.buildPropertyHolder; @@ -813,15 +812,15 @@ public class EmbeddableBinder { private static void processGeneratedId(MetadataBuildingContext context, Component component, MemberDetails property) { final GeneratedValue generatedValue = property.getDirectAnnotationUsage( GeneratedValue.class ); - final String generatorType = generatedValue != null - ? generatorType( generatedValue, property.getType().determineRawClass(), context ) - : GeneratorBinder.ASSIGNED_GENERATOR_NAME; - final String generator = generatedValue != null ? generatedValue.generator() : ""; + final String generatorType = + generatorStrategy( generatedValue.strategy(), generatedValue.generator(), property.getType() ); + final String generator = generatedValue.generator(); + final SimpleValue value = (SimpleValue) component.getProperty( property.getName()).getValue(); if ( isGlobalGeneratorNameGlobal( context ) ) { buildGenerators( property, context ); context.getMetadataCollector().addSecondPass( new IdGeneratorResolverSecondPass( - (SimpleValue) component.getProperty( property.getName() ).getValue(), + value, property, generatorType, generator, @@ -835,7 +834,7 @@ public class EmbeddableBinder { } else { makeIdGenerator( - (SimpleValue) component.getProperty( property.getName() ).getValue(), + value, property, generatorType, generator, diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/EntityBinder.java b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/EntityBinder.java index 9ef1339960..0c0f3af1d5 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/EntityBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/EntityBinder.java @@ -8,7 +8,6 @@ package org.hibernate.boot.model.internal; import java.lang.annotation.Annotation; import java.util.ArrayList; -import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -156,7 +155,6 @@ import static org.hibernate.boot.model.internal.BinderHelper.toAliasTableMap; import static org.hibernate.boot.model.internal.DialectOverridesAnnotationHelper.getOverridableAnnotation; import static org.hibernate.boot.model.internal.DialectOverridesAnnotationHelper.getOverrideAnnotation; import static org.hibernate.boot.model.internal.EmbeddableBinder.fillEmbeddable; -import static org.hibernate.boot.model.internal.GeneratorBinder.makeIdGenerator; import static org.hibernate.boot.model.internal.InheritanceState.getInheritanceStateOfSuperEntity; import static org.hibernate.boot.model.internal.PropertyBinder.addElementsOfClass; import static org.hibernate.boot.model.internal.PropertyBinder.hasIdAnnotation; @@ -749,8 +747,6 @@ public class EntityBinder { rootClass.setIdentifier( id ); - handleIdGenerator( inferredData, buildingContext, id ); - rootClass.setEmbeddedIdentifier( inferredData.getPropertyType() == null ); propertyHolder.setInIdClass( null ); @@ -758,28 +754,6 @@ public class EntityBinder { return id; } - private static void handleIdGenerator(PropertyData inferredData, MetadataBuildingContext buildingContext, Component id) { - if ( buildingContext.getBootstrapContext().getJpaCompliance().isGlobalGeneratorScopeEnabled() ) { - buildingContext.getMetadataCollector().addSecondPass( new IdGeneratorResolverSecondPass( - id, - inferredData.getAttributeMember(), - GeneratorBinder.ASSIGNED_GENERATOR_NAME, - "", - buildingContext - ) ); - } - else { - makeIdGenerator( - id, - inferredData.getAttributeMember(), - GeneratorBinder.ASSIGNED_GENERATOR_NAME, - "", - buildingContext, - Collections.emptyMap() - ); - } - } - private void handleSecondaryTables() { annotatedClass.forEachRepeatedAnnotationUsages( JpaAnnotations.SECONDARY_TABLE, getSourceModelContext(), (usage) -> { addSecondaryTable( usage, null, false ); 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 90429c7d4e..c93d11e626 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 @@ -6,29 +6,23 @@ */ package org.hibernate.boot.model.internal; -import java.lang.annotation.Annotation; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Member; -import java.util.HashMap; -import java.util.Map; -import java.util.Properties; - +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.SequenceGenerator; +import jakarta.persistence.TableGenerator; +import jakarta.persistence.Version; import org.hibernate.AnnotationException; +import org.hibernate.AssertionFailure; import org.hibernate.MappingException; import org.hibernate.annotations.GenericGenerator; import org.hibernate.annotations.IdGeneratorType; import org.hibernate.annotations.ValueGenerationType; -import org.hibernate.boot.internal.GenerationStrategyInterpreter; import org.hibernate.boot.model.IdentifierGeneratorDefinition; import org.hibernate.boot.model.relational.ExportableProducer; import org.hibernate.boot.model.source.internal.hbm.MappingDocument; -import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.boot.spi.InFlightMetadataCollector; import org.hibernate.boot.spi.MetadataBuildingContext; -import org.hibernate.cfg.AvailableSettings; -import org.hibernate.dialect.Dialect; -import org.hibernate.engine.config.spi.ConfigurationService; -import org.hibernate.engine.config.spi.StandardConverters; +import org.hibernate.boot.spi.PropertyData; import org.hibernate.generator.AnnotationBasedGenerator; import org.hibernate.generator.Assigned; import org.hibernate.generator.BeforeExecutionGenerator; @@ -36,27 +30,15 @@ import org.hibernate.generator.Generator; import org.hibernate.generator.GeneratorCreationContext; import org.hibernate.generator.OnExecutionGenerator; import org.hibernate.id.Configurable; -import org.hibernate.id.ForeignGenerator; -import org.hibernate.id.GUIDGenerator; import org.hibernate.id.IdentifierGenerator; import org.hibernate.id.IdentityGenerator; -import org.hibernate.id.IncrementGenerator; -import org.hibernate.id.OptimizableGenerator; import org.hibernate.id.PersistentIdentifierGenerator; -import org.hibernate.id.SelectGenerator; -import org.hibernate.id.UUIDGenerator; -import org.hibernate.id.UUIDHexGenerator; -import org.hibernate.id.enhanced.LegacyNamingStrategy; -import org.hibernate.id.enhanced.SequenceStyleGenerator; -import org.hibernate.id.enhanced.SingleNamingStrategy; import org.hibernate.internal.CoreLogging; -import org.hibernate.mapping.Column; +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.internal.util.collections.CollectionHelper; import org.hibernate.mapping.GeneratorCreator; -import org.hibernate.mapping.RootClass; import org.hibernate.mapping.SimpleValue; -import org.hibernate.mapping.Table; import org.hibernate.models.spi.AnnotationTarget; -import org.hibernate.models.spi.ClassDetails; import org.hibernate.models.spi.MemberDetails; import org.hibernate.models.spi.SourceModelBuildingContext; import org.hibernate.resource.beans.container.spi.BeanContainer; @@ -65,19 +47,25 @@ import org.hibernate.resource.beans.spi.ManagedBeanRegistry; import org.hibernate.service.ServiceRegistry; import org.hibernate.type.Type; -import org.jboss.logging.Logger; - -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.SequenceGenerator; -import jakarta.persistence.TableGenerator; -import jakarta.persistence.Version; +import java.lang.annotation.Annotation; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Member; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Properties; import static java.util.Collections.emptyMap; -import static org.hibernate.boot.internal.GenerationStrategyInterpreter.STRATEGY_INTERPRETER; import static org.hibernate.boot.model.internal.AnnotationHelper.extractParameterMap; -import static org.hibernate.boot.model.internal.BinderHelper.isCompositeId; +import static org.hibernate.boot.model.internal.BinderHelper.getPath; import static org.hibernate.boot.model.internal.BinderHelper.isGlobalGeneratorNameGlobal; +import static org.hibernate.boot.model.internal.GeneratorParameters.collectParameters; +import static org.hibernate.boot.model.internal.GeneratorParameters.interpretSequenceGenerator; +import static org.hibernate.boot.model.internal.GeneratorParameters.interpretTableGenerator; +import static org.hibernate.boot.model.internal.GeneratorStrategies.generatorClass; +import static org.hibernate.boot.model.internal.GeneratorStrategies.generatorStrategy; +import static org.hibernate.internal.util.StringHelper.qualify; import static org.hibernate.resource.beans.internal.Helper.allowExtensionsInCdi; /** @@ -87,7 +75,7 @@ import static org.hibernate.resource.beans.internal.Helper.allowExtensionsInCdi; */ public class GeneratorBinder { - private static final Logger LOG = CoreLogging.logger( GeneratorBinder.class ); + private static final CoreMessageLogger LOG = CoreLogging.messageLogger( GeneratorBinder.class ); public static final String ASSIGNED_GENERATOR_NAME = "assigned"; public static final GeneratorCreator ASSIGNED_IDENTIFIER_GENERATOR_CREATOR = @@ -103,144 +91,7 @@ public class GeneratorBinder { }; /** - * Interpret an "old" generator strategy name as a {@link Generator} class. - */ - private static Class generatorClass(String strategy, SimpleValue idValue) { - if ( "native".equals(strategy) ) { - strategy = - idValue.getMetadata().getDatabase().getDialect() - .getNativeIdentifierGeneratorStrategy(); - } - switch (strategy) { - case "assigned": - return org.hibernate.id.Assigned.class; - case "enhanced-sequence": - case "sequence": - return SequenceStyleGenerator.class; - case "enhanced-table": - case "table": - return org.hibernate.id.enhanced.TableGenerator.class; - case "identity": - return IdentityGenerator.class; - case "increment": - return IncrementGenerator.class; - case "foreign": - return ForeignGenerator.class; - case "uuid": - case "uuid.hex": - return UUIDHexGenerator.class; - case "uuid2": - return UUIDGenerator.class; - case "select": - return SelectGenerator.class; - case "guid": - return GUIDGenerator.class; - } - final Class clazz = - idValue.getServiceRegistry().requireService( 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; - } - - /** - * Collect the parameters which should be passed to - * {@link Configurable#configure(Type, Properties, ServiceRegistry)}. - */ - public static Properties collectParameters( - SimpleValue identifierValue, - Dialect dialect, - RootClass rootClass, - Map configuration) { - final ConfigurationService configService = - identifierValue.getMetadata().getMetadataBuildingOptions().getServiceRegistry() - .requireService( ConfigurationService.class ); - - final Properties params = new Properties(); - - // default initial value and allocation size per-JPA defaults - params.setProperty( OptimizableGenerator.INITIAL_PARAM, - String.valueOf( OptimizableGenerator.DEFAULT_INITIAL_VALUE ) ); - - params.setProperty( OptimizableGenerator.INCREMENT_PARAM, - String.valueOf( defaultIncrement( 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 - final String tableName = identifierValue.getTable().getQuotedName( dialect ); - params.setProperty( PersistentIdentifierGenerator.TABLE, tableName ); - - //pass the column name (a generated id almost always has a single column) - final Column column = (Column) identifierValue.getSelectables().get(0); - final String columnName = column.getQuotedName( dialect ); - params.setProperty( PersistentIdentifierGenerator.PK, columnName ); - - //pass the entity-name, if not a collection-id - if ( rootClass != null ) { - params.setProperty( IdentifierGenerator.ENTITY_NAME, rootClass.getEntityName() ); - params.setProperty( IdentifierGenerator.JPA_ENTITY_NAME, rootClass.getJpaEntityName() ); - // The table name is not really a good default for subselect entities, - // so use the JPA entity name which is short - params.setProperty( OptimizableGenerator.IMPLICIT_NAME_BASE, - identifierValue.getTable().isSubselect() - ? rootClass.getJpaEntityName() - : identifierValue.getTable().getName() ); - - params.setProperty( PersistentIdentifierGenerator.TABLES, - identityTablesString( dialect, rootClass ) ); - } - else { - params.setProperty( PersistentIdentifierGenerator.TABLES, tableName ); - params.setProperty( OptimizableGenerator.IMPLICIT_NAME_BASE, tableName ); - } - - params.put( IdentifierGenerator.CONTRIBUTOR_NAME, - identifierValue.getBuildingContext().getCurrentContributorName() ); - - final Map settings = configService.getSettings(); - if ( settings.containsKey( AvailableSettings.PREFERRED_POOLED_OPTIMIZER ) ) { - params.put( AvailableSettings.PREFERRED_POOLED_OPTIMIZER, - settings.get( AvailableSettings.PREFERRED_POOLED_OPTIMIZER ) ); - } - - params.putAll( configuration ); - - return params; - } - - private static String identityTablesString(Dialect dialect, RootClass rootClass) { - final StringBuilder tables = new StringBuilder(); - for ( Table table : rootClass.getIdentityTables() ) { - tables.append( table.getQuotedName( dialect ) ); - if ( !tables.isEmpty() ) { - tables.append( ", " ); - } - } - return tables.toString(); - } - - private static int defaultIncrement(ConfigurationService configService) { - final String idNamingStrategy = - configService.getSetting( AvailableSettings.ID_DB_STRUCTURE_NAMING_STRATEGY, - StandardConverters.STRING, null ); - if ( LegacyNamingStrategy.STRATEGY_NAME.equals( idNamingStrategy ) - || LegacyNamingStrategy.class.getName().equals( idNamingStrategy ) - || SingleNamingStrategy.STRATEGY_NAME.equals( idNamingStrategy ) - || SingleNamingStrategy.class.getName().equals( idNamingStrategy ) ) { - return 1; - } - else { - return OptimizableGenerator.DEFAULT_INCREMENT_SIZE; - } - } - - /** - * Apply an id generation strategy and parameters to the - * given {@link SimpleValue} which represents an identifier. + * Create a generator, based on a {@link GeneratedValue} annotation. */ public static void makeIdGenerator( SimpleValue id, @@ -252,20 +103,15 @@ public class GeneratorBinder { //generator settings final Map configuration = new HashMap<>(); - - //always settable + configuration.put( IdentifierGenerator.GENERATOR_NAME, generatorName ); configuration.put( PersistentIdentifierGenerator.TABLE, id.getTable().getName() ); - if ( id.getColumnSpan() == 1 ) { configuration.put( PersistentIdentifierGenerator.PK, id.getColumns().get(0).getName() ); } - // YUCK! but cannot think of a clean way to do this given the string-config based scheme - configuration.put( PersistentIdentifierGenerator.IDENTIFIER_NORMALIZER, context.getObjectNameNormalizer() ); - configuration.put( IdentifierGenerator.GENERATOR_NAME, generatorName ); final String generatorStrategy = determineStrategy( idAttributeMember, generatorType, generatorName, context, localGenerators, configuration ); - setGeneratorCreator( id, configuration, generatorStrategy, beanContainer( context ) ); + setGeneratorCreator( id, configuration, generatorStrategy, context ); } private static String determineStrategy( @@ -300,22 +146,6 @@ public class GeneratorBinder { } } - /** - * apply an id generator to a SimpleValue - */ - public static void makeIdGenerator( - SimpleValue id, - MemberDetails idAttributeMember, - String generatorType, - String generatorName, - MetadataBuildingContext buildingContext, - IdentifierGeneratorDefinition foreignKGeneratorDefinition) { - makeIdGenerator( id, idAttributeMember, generatorType, generatorName, buildingContext, - foreignKGeneratorDefinition != null - ? Map.of( foreignKGeneratorDefinition.getName(), foreignKGeneratorDefinition ) - : null ); - } - private static IdentifierGeneratorDefinition makeIdentifierGeneratorDefinition( String name, MemberDetails idAttributeMember, @@ -338,13 +168,12 @@ public class GeneratorBinder { final GeneratedValue generatedValue = idAttributeMember.getDirectAnnotationUsage( GeneratedValue.class ); if ( generatedValue == null ) { - // this should really never happen, but it's easy to protect against it... - return new IdentifierGeneratorDefinition(ASSIGNED_GENERATOR_NAME, ASSIGNED_GENERATOR_NAME); + throw new AssertionFailure( "No @GeneratedValue annotation" ); } return IdentifierGeneratorDefinition.createImplicit( name, - idAttributeMember.getType().determineRawClass().toJavaClass(), + idAttributeMember.getType(), generatedValue.generator(), interpretGenerationType( generatedValue ) ); @@ -356,6 +185,10 @@ public class GeneratorBinder { return strategy == null ? GenerationType.AUTO : strategy; } + /** + * Build any generators declared using {@link TableGenerator}, {@link SequenceGenerator}, + * and {@link GenericGenerator} annotations of the given program element. + */ public static Map buildGenerators( AnnotationTarget annotatedElement, MetadataBuildingContext context) { @@ -364,19 +197,19 @@ public class GeneratorBinder { final Map generators = new HashMap<>(); annotatedElement.forEachAnnotationUsage( TableGenerator.class, sourceModelContext, (usage) -> { - IdentifierGeneratorDefinition idGenerator = buildIdGenerator( usage, context ); + IdentifierGeneratorDefinition idGenerator = buildTableIdGenerator( usage ); generators.put( idGenerator.getName(), idGenerator ); metadataCollector.addIdentifierGenerator( idGenerator ); } ); annotatedElement.forEachAnnotationUsage( SequenceGenerator.class, sourceModelContext, (usage) -> { - IdentifierGeneratorDefinition idGenerator = buildIdGenerator( usage, context ); + IdentifierGeneratorDefinition idGenerator = buildSequenceIdGenerator( usage ); generators.put( idGenerator.getName(), idGenerator ); metadataCollector.addIdentifierGenerator( idGenerator ); } ); annotatedElement.forEachAnnotationUsage( GenericGenerator.class, sourceModelContext, (usage) -> { - final IdentifierGeneratorDefinition idGenerator = buildIdGenerator( usage, context ); + final IdentifierGeneratorDefinition idGenerator = buildIdGenerator( usage ); generators.put( idGenerator.getName(), idGenerator ); metadataCollector.addIdentifierGenerator( idGenerator ); } ); @@ -384,87 +217,38 @@ public class GeneratorBinder { return generators; } - static String generatorType( - MetadataBuildingContext context, - ClassDetails entityXClass, - boolean isComponent, - GeneratedValue generatedValue) { - if ( isComponent ) { - //a component must not have any generator - return ASSIGNED_GENERATOR_NAME; - } - else { - return generatedValue == null ? ASSIGNED_GENERATOR_NAME : generatorType( generatedValue, entityXClass, context ); - } - } + private static IdentifierGeneratorDefinition buildIdGenerator(GenericGenerator generatorAnnotation) { + final IdentifierGeneratorDefinition.Builder definitionBuilder = + new IdentifierGeneratorDefinition.Builder(); + definitionBuilder.setName( generatorAnnotation.name() ); + final Class generatorClass = generatorAnnotation.type(); + final String strategy = + generatorClass.equals( Generator.class ) + ? generatorAnnotation.strategy() + : generatorClass.getName(); + definitionBuilder.setStrategy( strategy ); + definitionBuilder.addParams( extractParameterMap( generatorAnnotation.parameters() ) ); - static String generatorType( - GeneratedValue generatedValue, - final ClassDetails javaClass, - MetadataBuildingContext context) { - return STRATEGY_INTERPRETER.determineGeneratorName( - generatedValue.strategy(), - new GenerationStrategyInterpreter.GeneratorNameDeterminationContext() { - Class javaType = null; - @Override - public Class getIdType() { - if ( javaType == null ) { - javaType = javaClass.toJavaClass(); - } - return javaType; - } - @Override - public String getGeneratedValueGeneratorName() { - return generatedValue.generator(); - } - } - ); - } - - static IdentifierGeneratorDefinition buildIdGenerator( - Annotation generatorAnnotation, - MetadataBuildingContext context) { - if ( generatorAnnotation == null ) { - return null; - } - - final IdentifierGeneratorDefinition.Builder definitionBuilder = new IdentifierGeneratorDefinition.Builder(); - if ( generatorAnnotation instanceof TableGenerator tableGenerator ) { - STRATEGY_INTERPRETER.interpretTableGenerator( tableGenerator, definitionBuilder ); - if ( LOG.isTraceEnabled() ) { - LOG.tracev( "Add table generator with name: {0}", definitionBuilder.getName() ); - } - } - else if ( generatorAnnotation instanceof SequenceGenerator sequenceGenerator ) { - STRATEGY_INTERPRETER.interpretSequenceGenerator( sequenceGenerator, definitionBuilder ); - if ( LOG.isTraceEnabled() ) { - LOG.tracev( "Add sequence generator with name: {0}", definitionBuilder.getName() ); - } - } - else if ( generatorAnnotation instanceof GenericGenerator genericGenerator ) { - definitionBuilder.setName( genericGenerator.name() ); - final Class generatorClass = genericGenerator.type(); - final String strategy = - generatorClass.equals( Generator.class ) - ? genericGenerator.strategy() - : generatorClass.getName(); - definitionBuilder.setStrategy( strategy ); - definitionBuilder.addParams( extractParameterMap( genericGenerator.parameters() ) ); - if ( LOG.isTraceEnabled() ) { - LOG.tracev( "Add generic generator with name: {0}", definitionBuilder.getName() ); - } + if ( LOG.isTraceEnabled() ) { + LOG.tracev( "Added generator with name: {0}, strategy: {0}", + definitionBuilder.getName(), definitionBuilder.getStrategy() ); } return definitionBuilder.build(); } - static IdentifierGeneratorDefinition buildSequenceIdGenerator(SequenceGenerator generatorAnnotation) { - if ( generatorAnnotation == null ) { - return null; - } - + private static IdentifierGeneratorDefinition buildSequenceIdGenerator(SequenceGenerator generatorAnnotation) { final IdentifierGeneratorDefinition.Builder definitionBuilder = new IdentifierGeneratorDefinition.Builder(); - STRATEGY_INTERPRETER.interpretSequenceGenerator( generatorAnnotation, definitionBuilder ); + interpretSequenceGenerator( generatorAnnotation, definitionBuilder ); + if ( LOG.isTraceEnabled() ) { + LOG.tracev( "Add sequence generator with name: {0}", definitionBuilder.getName() ); + } + return definitionBuilder.build(); + } + + private static IdentifierGeneratorDefinition buildTableIdGenerator(TableGenerator generatorAnnotation) { + final IdentifierGeneratorDefinition.Builder definitionBuilder = new IdentifierGeneratorDefinition.Builder(); + interpretTableGenerator( generatorAnnotation, definitionBuilder ); if ( LOG.isTraceEnabled() ) { LOG.tracev( "Add sequence generator with name: {0}", definitionBuilder.getName() ); } @@ -494,20 +278,16 @@ public class GeneratorBinder { } /** - * In case the given annotation is a value generator annotation, the corresponding value generation strategy to be - * applied to the given property is returned, {@code null} otherwise. - * Instantiates the given generator annotation type, initializing it with the given instance of the corresponding - * generator annotation and the property's type. + * Return a {@link GeneratorCreator} for an attribute annotated + * with a {@linkplain ValueGenerationType generator annotation}. */ - static GeneratorCreator generatorCreator( + private static GeneratorCreator generatorCreator( MemberDetails memberDetails, Annotation annotation, BeanContainer beanContainer) { final Class annotationType = annotation.annotationType(); final ValueGenerationType generatorAnnotation = annotationType.getAnnotation( ValueGenerationType.class ); - if ( generatorAnnotation == null ) { - return null; - } + assert generatorAnnotation != null; final Class generatorClass = generatorAnnotation.generatedBy(); checkGeneratorClass( generatorClass ); checkGeneratorInterfaces( generatorClass ); @@ -527,15 +307,19 @@ public class GeneratorBinder { }; } - static GeneratorCreator identifierGeneratorCreator( + /** + * Return a {@link GeneratorCreator} for an id attribute annotated + * with an {@linkplain IdGeneratorType id generator annotation}. + */ + private static GeneratorCreator identifierGeneratorCreator( MemberDetails idAttributeMember, Annotation annotation, SimpleValue identifierValue, BeanContainer beanContainer) { final Class annotationType = annotation.annotationType(); - final IdGeneratorType idGeneratorType = annotationType.getAnnotation( IdGeneratorType.class ); - assert idGeneratorType != null; - final Class generatorClass = idGeneratorType.value(); + final IdGeneratorType idGeneratorAnnotation = annotationType.getAnnotation( IdGeneratorType.class ); + assert idGeneratorAnnotation != null; + final Class generatorClass = idGeneratorAnnotation.value(); checkGeneratorClass( generatorClass ); return creationContext -> { final Generator generator = @@ -562,7 +346,7 @@ public class GeneratorBinder { * @param beanContainer an optional {@code BeanContainer} * @param generatorClass a class which implements {@code Generator} */ - private static Generator instantiateGenerator( + private static Generator instantiateGenerator( Annotation annotation, BeanContainer beanContainer, GeneratorCreationContext creationContext, @@ -807,23 +591,26 @@ public class GeneratorBinder { } } - static void createIdGenerator( + /** + * Create a generator, based on a {@link GeneratedValue} annotation. + */ + private static void createIdGenerator( SimpleValue idValue, Map classGenerators, MetadataBuildingContext context, - ClassDetails entityClass, - MemberDetails idAttributeMember) { + MemberDetails idMember) { //manage composite related metadata //guess if its a component and find id data access (property, field etc) - final GeneratedValue generatedValue = idAttributeMember.getDirectAnnotationUsage( GeneratedValue.class ); - final String generatorType = generatorType( context, entityClass, isCompositeId( entityClass, idAttributeMember ), generatedValue ); - final String generatorName = generatedValue == null ? "" : generatedValue.generator(); + final GeneratedValue generatedValue = idMember.getDirectAnnotationUsage( GeneratedValue.class ); + final String generatorType = + generatorStrategy( generatedValue.strategy(), generatedValue.generator(), idMember.getType() ); + final String generatorName = generatedValue.generator(); if ( isGlobalGeneratorNameGlobal( context ) ) { - buildGenerators( idAttributeMember, context ); + buildGenerators( idMember, context ); context.getMetadataCollector() .addSecondPass( new IdGeneratorResolverSecondPass( idValue, - idAttributeMember, + idMember, generatorType, generatorName, context @@ -832,8 +619,8 @@ public class GeneratorBinder { else { //clone classGenerator and override with local values final Map generators = new HashMap<>( classGenerators ); - generators.putAll( buildGenerators( idAttributeMember, context ) ); - makeIdGenerator( idValue, idAttributeMember, generatorType, generatorName, context, generators ); + generators.putAll( buildGenerators( idMember, context ) ); + makeIdGenerator( idValue, idMember, generatorType, generatorName, context, generators ); } } @@ -846,14 +633,14 @@ public class GeneratorBinder { final MappingDocument sourceDocument, IdentifierGeneratorDefinition definition, SimpleValue identifierValue, - MetadataBuildingContext buildingContext) { + MetadataBuildingContext context) { if ( definition != null ) { - final Map configuration = new HashMap<>(); - // see if the specified generator name matches a registered final IdentifierGeneratorDefinition generatorDef = - sourceDocument.getMetadataCollector().getIdentifierGenerator( definition.getName() ); + sourceDocument.getMetadataCollector() + .getIdentifierGenerator( definition.getName() ); + final Map configuration = new HashMap<>(); final String generatorStrategy; if ( generatorDef != null ) { generatorStrategy = generatorDef.getStrategy(); @@ -863,20 +650,16 @@ public class GeneratorBinder { generatorStrategy = definition.getStrategy(); } - // YUCK! but cannot think of a clean way to do this given the string-config based scheme - configuration.put( PersistentIdentifierGenerator.IDENTIFIER_NORMALIZER, - buildingContext.getObjectNameNormalizer() ); - configuration.putAll( definition.getParameters() ); - setGeneratorCreator( identifierValue, configuration, generatorStrategy, beanContainer( buildingContext ) ); + setGeneratorCreator( identifierValue, configuration, generatorStrategy, context ); } } /** * Obtain a {@link BeanContainer} to be used for instantiating generators. */ - static BeanContainer beanContainer(MetadataBuildingContext buildingContext) { + private static BeanContainer beanContainer(MetadataBuildingContext buildingContext) { final ServiceRegistry serviceRegistry = buildingContext.getBootstrapContext().getServiceRegistry(); return allowExtensionsInCdi( serviceRegistry ) ? serviceRegistry.requireService( ManagedBeanRegistry.class ).getBeanContainer() @@ -891,12 +674,13 @@ public class GeneratorBinder { SimpleValue identifierValue, Map configuration, String generatorStrategy, - BeanContainer beanContainer) { + MetadataBuildingContext context) { if ( ASSIGNED_GENERATOR_NAME.equals( generatorStrategy ) || org.hibernate.id.Assigned.class.getName().equals( generatorStrategy ) ) { identifierValue.setCustomIdGeneratorCreator( ASSIGNED_IDENTIFIER_GENERATOR_CREATOR ); } else { + final BeanContainer beanContainer = beanContainer( context ); identifierValue.setCustomIdGeneratorCreator( creationContext -> { final Generator identifierGenerator = instantiateGenerator( beanContainer, generatorClass( generatorStrategy, identifierValue ) ); @@ -908,4 +692,82 @@ public class GeneratorBinder { } ); } } + + /** + * Set up the id generator by considering all annotations of the identifier + * field, including {@linkplain IdGeneratorType id generator annotations}, + * and {@link GeneratedValue}. + */ + static void createIdGeneratorsFromGeneratorAnnotations( + PropertyHolder propertyHolder, + PropertyData inferredData, + SimpleValue idValue, + Map classGenerators, + MetadataBuildingContext context) { + + final SourceModelBuildingContext sourceModelContext = + context.getMetadataCollector().getSourceModelBuildingContext(); + final MemberDetails idAttributeMember = inferredData.getAttributeMember(); + final List idGeneratorAnnotations = + idAttributeMember.getMetaAnnotated( IdGeneratorType.class, sourceModelContext ); + final List generatorAnnotations = + idAttributeMember.getMetaAnnotated( ValueGenerationType.class, sourceModelContext ); + // Since these collections may contain Proxies created by common-annotations module we cannot reliably use simple remove/removeAll + // collection methods as those proxies do not implement hashcode/equals and even a simple `a.equals(a)` will return `false`. + // Instead, we will check the annotation types, since generator annotations should not be "repeatable" we should have only + // at most one annotation for a generator: + for ( Annotation id : idGeneratorAnnotations ) { + generatorAnnotations.removeIf( gen -> gen.annotationType().equals( id.annotationType() ) ); + } + + if ( idGeneratorAnnotations.size() + generatorAnnotations.size() > 1 ) { + throw new AnnotationException( String.format( + Locale.ROOT, + "Identifier attribute '%s' has too many generator annotations: %s", + getPath( propertyHolder, inferredData ), + CollectionHelper.combineUntyped( idGeneratorAnnotations, generatorAnnotations ) + ) ); + } + if ( !idGeneratorAnnotations.isEmpty() ) { + idValue.setCustomIdGeneratorCreator( identifierGeneratorCreator( + idAttributeMember, + idGeneratorAnnotations.get(0), + idValue, + beanContainer( context ) + ) ); + } + else if ( !generatorAnnotations.isEmpty() ) { +// idValue.setCustomGeneratorCreator( generatorCreator( idAttributeMember, generatorAnnotation ) ); + throw new AnnotationException( String.format( + Locale.ROOT, + "Identifier attribute '%s' is annotated '%s' which is not an '@IdGeneratorType'", + getPath( propertyHolder, inferredData ), + generatorAnnotations.get(0).annotationType() + ) ); + } + else if ( idAttributeMember.hasDirectAnnotationUsage( GeneratedValue.class ) ) { + createIdGenerator( idValue, classGenerators, context, idAttributeMember ); + } + } + + /** + * Returns the value generation strategy for the given property, if any, by + * considering {@linkplain ValueGenerationType generator type annotations}. + */ + static GeneratorCreator createValueGeneratorFromAnnotations( + PropertyHolder holder, String propertyName, + MemberDetails property, MetadataBuildingContext context) { + final List generatorAnnotations = + property.getMetaAnnotated( ValueGenerationType.class, + context.getMetadataCollector().getSourceModelBuildingContext() ); + switch ( generatorAnnotations.size() ) { + case 0: + return null; + case 1: + return generatorCreator( property, 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 new file mode 100644 index 0000000000..84481179f7 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/GeneratorParameters.java @@ -0,0 +1,253 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html. + */ +package org.hibernate.boot.model.internal; + +import jakarta.persistence.SequenceGenerator; +import jakarta.persistence.TableGenerator; +import jakarta.persistence.UniqueConstraint; +import org.hibernate.Internal; +import org.hibernate.boot.model.IdentifierGeneratorDefinition; +import org.hibernate.cfg.AvailableSettings; +import org.hibernate.dialect.Dialect; +import org.hibernate.engine.config.spi.ConfigurationService; +import org.hibernate.engine.config.spi.StandardConverters; +import org.hibernate.id.Configurable; +import org.hibernate.id.IdentifierGenerator; +import org.hibernate.id.OptimizableGenerator; +import org.hibernate.id.PersistentIdentifierGenerator; +import org.hibernate.id.enhanced.LegacyNamingStrategy; +import org.hibernate.id.enhanced.SequenceStyleGenerator; +import org.hibernate.id.enhanced.SingleNamingStrategy; +import org.hibernate.internal.CoreLogging; +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.mapping.Column; +import org.hibernate.mapping.RootClass; +import org.hibernate.mapping.SimpleValue; +import org.hibernate.mapping.Table; +import org.hibernate.service.ServiceRegistry; +import org.hibernate.type.Type; + +import java.util.Map; +import java.util.Properties; + +/** + * Responsible for setting up the parameters which are passed to + * {@link Configurable#configure(Type, Properties, ServiceRegistry)} + * when a {@link Configurable} generator is instantiated. + * + * @since 7.0 + * + * @author Gavin King + */ +public class GeneratorParameters { + + private static final CoreMessageLogger LOG = CoreLogging.messageLogger( GeneratorBinder.class ); + + /** + * Collect the parameters which should be passed to + * {@link Configurable#configure(Type, Properties, ServiceRegistry)}. + */ + public static Properties collectParameters( + SimpleValue identifierValue, + Dialect dialect, + RootClass rootClass, + Map configuration) { + final ConfigurationService configService = + identifierValue.getMetadata().getMetadataBuildingOptions().getServiceRegistry() + .requireService( ConfigurationService.class ); + + final Properties params = new Properties(); + + // default initial value and allocation size per-JPA defaults + params.setProperty( OptimizableGenerator.INITIAL_PARAM, + String.valueOf( OptimizableGenerator.DEFAULT_INITIAL_VALUE ) ); + + params.setProperty( OptimizableGenerator.INCREMENT_PARAM, + String.valueOf( defaultIncrement( 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 + final String tableName = identifierValue.getTable().getQuotedName( dialect ); + params.setProperty( PersistentIdentifierGenerator.TABLE, tableName ); + + //pass the column name (a generated id almost always has a single column) + final Column column = (Column) identifierValue.getSelectables().get(0); + final String columnName = column.getQuotedName( dialect ); + params.setProperty( PersistentIdentifierGenerator.PK, columnName ); + + //pass the entity-name, if not a collection-id + if ( rootClass != null ) { + params.setProperty( IdentifierGenerator.ENTITY_NAME, rootClass.getEntityName() ); + params.setProperty( IdentifierGenerator.JPA_ENTITY_NAME, rootClass.getJpaEntityName() ); + // The table name is not really a good default for subselect entities, + // so use the JPA entity name which is short + params.setProperty( OptimizableGenerator.IMPLICIT_NAME_BASE, + identifierValue.getTable().isSubselect() + ? rootClass.getJpaEntityName() + : identifierValue.getTable().getName() ); + + params.setProperty( PersistentIdentifierGenerator.TABLES, + identityTablesString( dialect, rootClass ) ); + } + else { + params.setProperty( PersistentIdentifierGenerator.TABLES, tableName ); + params.setProperty( OptimizableGenerator.IMPLICIT_NAME_BASE, tableName ); + } + + params.put( IdentifierGenerator.CONTRIBUTOR_NAME, + identifierValue.getBuildingContext().getCurrentContributorName() ); + + final Map settings = configService.getSettings(); + if ( settings.containsKey( AvailableSettings.PREFERRED_POOLED_OPTIMIZER ) ) { + params.put( AvailableSettings.PREFERRED_POOLED_OPTIMIZER, + settings.get( AvailableSettings.PREFERRED_POOLED_OPTIMIZER ) ); + } + + params.putAll( configuration ); + + return params; + } + + private static String identityTablesString(Dialect dialect, RootClass rootClass) { + final StringBuilder tables = new StringBuilder(); + for ( Table table : rootClass.getIdentityTables() ) { + tables.append( table.getQuotedName( dialect ) ); + if ( !tables.isEmpty() ) { + tables.append( ", " ); + } + } + return tables.toString(); + } + + private static int defaultIncrement(ConfigurationService configService) { + final String idNamingStrategy = + configService.getSetting( AvailableSettings.ID_DB_STRUCTURE_NAMING_STRATEGY, + StandardConverters.STRING, null ); + if ( LegacyNamingStrategy.STRATEGY_NAME.equals( idNamingStrategy ) + || LegacyNamingStrategy.class.getName().equals( idNamingStrategy ) + || SingleNamingStrategy.STRATEGY_NAME.equals( idNamingStrategy ) + || SingleNamingStrategy.class.getName().equals( idNamingStrategy ) ) { + return 1; + } + else { + return OptimizableGenerator.DEFAULT_INCREMENT_SIZE; + } + } + + + @Internal + public static void interpretTableGenerator( + TableGenerator tableGeneratorAnnotation, + IdentifierGeneratorDefinition.Builder definitionBuilder) { + definitionBuilder.setName( tableGeneratorAnnotation.name() ); + definitionBuilder.setStrategy( org.hibernate.id.enhanced.TableGenerator.class.getName() ); + definitionBuilder.addParam( org.hibernate.id.enhanced.TableGenerator.CONFIG_PREFER_SEGMENT_PER_ENTITY, "true" ); + + final String catalog = tableGeneratorAnnotation.catalog(); + if ( StringHelper.isNotEmpty( catalog ) ) { + definitionBuilder.addParam( PersistentIdentifierGenerator.CATALOG, catalog ); + } + + final String schema = tableGeneratorAnnotation.schema(); + if ( StringHelper.isNotEmpty( schema ) ) { + definitionBuilder.addParam( PersistentIdentifierGenerator.SCHEMA, schema ); + } + + final String table = tableGeneratorAnnotation.table(); + if ( StringHelper.isNotEmpty( table ) ) { + definitionBuilder.addParam( org.hibernate.id.enhanced.TableGenerator.TABLE_PARAM, table ); + } + + final String pkColumnName = tableGeneratorAnnotation.pkColumnName(); + if ( StringHelper.isNotEmpty( pkColumnName ) ) { + definitionBuilder.addParam( + org.hibernate.id.enhanced.TableGenerator.SEGMENT_COLUMN_PARAM, + pkColumnName + ); + } + + final String pkColumnValue = tableGeneratorAnnotation.pkColumnValue(); + if ( StringHelper.isNotEmpty( pkColumnValue ) ) { + definitionBuilder.addParam( + org.hibernate.id.enhanced.TableGenerator.SEGMENT_VALUE_PARAM, + pkColumnValue + ); + } + + final String valueColumnName = tableGeneratorAnnotation.valueColumnName(); + if ( StringHelper.isNotEmpty( valueColumnName ) ) { + definitionBuilder.addParam( + org.hibernate.id.enhanced.TableGenerator.VALUE_COLUMN_PARAM, + valueColumnName + ); + } + + final String options = tableGeneratorAnnotation.options(); + if ( StringHelper.isNotEmpty( options ) ) { + definitionBuilder.addParam( + PersistentIdentifierGenerator.OPTIONS, + options + ); + } + + definitionBuilder.addParam( + org.hibernate.id.enhanced.TableGenerator.INCREMENT_PARAM, + String.valueOf( tableGeneratorAnnotation.allocationSize() ) + ); + + // See comment on HHH-4884 wrt initialValue. Basically initialValue is really the stated value + 1 + definitionBuilder.addParam( + org.hibernate.id.enhanced.TableGenerator.INITIAL_PARAM, + String.valueOf( tableGeneratorAnnotation.initialValue() + 1 ) + ); + + // TODO : implement unique-constraint support + final UniqueConstraint[] uniqueConstraints = tableGeneratorAnnotation.uniqueConstraints(); + if ( CollectionHelper.isNotEmpty( uniqueConstraints ) ) { + LOG.ignoringTableGeneratorConstraints( tableGeneratorAnnotation.name() ); + } + } + + @Internal + public static void interpretSequenceGenerator( + SequenceGenerator sequenceGeneratorAnnotation, + IdentifierGeneratorDefinition.Builder definitionBuilder) { + definitionBuilder.setName( sequenceGeneratorAnnotation.name() ); + definitionBuilder.setStrategy( SequenceStyleGenerator.class.getName() ); + + final String catalog = sequenceGeneratorAnnotation.catalog(); + if ( StringHelper.isNotEmpty( catalog ) ) { + definitionBuilder.addParam( PersistentIdentifierGenerator.CATALOG, catalog ); + } + + final String schema = sequenceGeneratorAnnotation.schema(); + if ( StringHelper.isNotEmpty( schema ) ) { + definitionBuilder.addParam( PersistentIdentifierGenerator.SCHEMA, schema ); + } + + final String sequenceName = sequenceGeneratorAnnotation.sequenceName(); + if ( StringHelper.isNotEmpty( sequenceName ) ) { + definitionBuilder.addParam( SequenceStyleGenerator.SEQUENCE_PARAM, sequenceName ); + } + + definitionBuilder.addParam( + SequenceStyleGenerator.INCREMENT_PARAM, + String.valueOf( sequenceGeneratorAnnotation.allocationSize() ) + ); + definitionBuilder.addParam( + SequenceStyleGenerator.INITIAL_PARAM, + String.valueOf( sequenceGeneratorAnnotation.initialValue() ) + ); + + final String options = sequenceGeneratorAnnotation.options(); + if ( StringHelper.isNotEmpty( options ) ) { + definitionBuilder.addParam( PersistentIdentifierGenerator.OPTIONS, options ); + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/GeneratorStrategies.java b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/GeneratorStrategies.java new file mode 100644 index 0000000000..e4f4c7b306 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/GeneratorStrategies.java @@ -0,0 +1,116 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html. + */ +package org.hibernate.boot.model.internal; + +import jakarta.persistence.GenerationType; +import org.hibernate.MappingException; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.generator.Generator; +import org.hibernate.id.ForeignGenerator; +import org.hibernate.id.GUIDGenerator; +import org.hibernate.id.IdentityGenerator; +import org.hibernate.id.IncrementGenerator; +import org.hibernate.id.SelectGenerator; +import org.hibernate.id.UUIDGenerator; +import org.hibernate.id.UUIDHexGenerator; +import org.hibernate.id.enhanced.SequenceStyleGenerator; +import org.hibernate.mapping.SimpleValue; +import org.hibernate.models.spi.TypeDetails; + +import java.util.UUID; + +/** + * Handles interpretation of old {@code hbm.xml}-style generator strategy names. + * + * @since 7.0 + * + * @author Gavin King + */ +public class GeneratorStrategies { + + /** + * Interpret a JPA {@link GenerationType} as an old-style generator strategy name. + * + * @param generationType the type specified by {@link jakarta.persistence.GeneratedValue#strategy} + * @param name the name specified by {@link jakarta.persistence.GeneratedValue#generator} + * @param type the Java type of the generated identifier + * @return a {@code hbml.xml}-equivalent string identifying the strategy + */ + public static String generatorStrategy(GenerationType generationType, String name, TypeDetails type) { + switch ( generationType ) { + case IDENTITY: + return "identity"; + case SEQUENCE: + return SequenceStyleGenerator.class.getName(); + case TABLE: + return org.hibernate.id.enhanced.TableGenerator.class.getName(); + case UUID: + return UUIDGenerator.class.getName(); + case AUTO: + if ( UUID.class.isAssignableFrom( type.determineRawClass().toJavaClass() ) ) { + return UUIDGenerator.class.getName(); + } + else if ( "increment".equalsIgnoreCase( name ) ) { + // 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: + throw new IllegalArgumentException( "Unsupported generation type:" + generationType ); + } + } + + /** + * Interpret an "old" generator strategy name as a {@link Generator} class. + */ + public static Class generatorClass(String strategy, SimpleValue idValue) { + if ( "native".equals(strategy) ) { + strategy = + idValue.getMetadata().getDatabase().getDialect() + .getNativeIdentifierGeneratorStrategy(); + } + switch (strategy) { + case "assigned": + return org.hibernate.id.Assigned.class; + case "enhanced-sequence": + case "sequence": + return SequenceStyleGenerator.class; + case "enhanced-table": + case "table": + return org.hibernate.id.enhanced.TableGenerator.class; + case "identity": + return IdentityGenerator.class; + case "increment": + return IncrementGenerator.class; + case "foreign": + return ForeignGenerator.class; + case "uuid": + case "uuid.hex": + return UUIDHexGenerator.class; + case "uuid2": + return UUIDGenerator.class; + case "select": + return SelectGenerator.class; + case "guid": + return GUIDGenerator.class; + } + final Class clazz = + idValue.getServiceRegistry().requireService( 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; + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/IdBagBinder.java b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/IdBagBinder.java index df8c1c20aa..76ee26e514 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/IdBagBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/IdBagBinder.java @@ -26,6 +26,7 @@ import org.hibernate.usertype.UserCollectionType; import jakarta.persistence.Column; +import static org.hibernate.boot.model.internal.BinderHelper.isGlobalGeneratorNameGlobal; import static org.hibernate.boot.model.internal.GeneratorBinder.makeIdGenerator; /** @@ -131,7 +132,7 @@ public class IdBagBinder extends BagBinder { generatorName = namedGenerator; } - if ( buildingContext.getBootstrapContext().getJpaCompliance().isGlobalGeneratorScopeEnabled() ) { + if ( isGlobalGeneratorNameGlobal( buildingContext ) ) { SecondPass secondPass = new IdGeneratorResolverSecondPass( id, property, 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 523b42b107..7278c23bae 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 @@ -9,7 +9,6 @@ package org.hibernate.boot.model.internal; import java.util.Map; import org.hibernate.MappingException; -import org.hibernate.boot.model.IdentifierGeneratorDefinition; import org.hibernate.boot.spi.MetadataBuildingContext; import org.hibernate.boot.spi.SecondPass; import org.hibernate.mapping.PersistentClass; @@ -27,7 +26,7 @@ public class IdGeneratorResolverSecondPass implements SecondPass { private final String generatorType; private final String generatorName; private final MetadataBuildingContext buildingContext; - private IdentifierGeneratorDefinition localIdentifierGeneratorDefinition; +// private IdentifierGeneratorDefinition localIdentifierGeneratorDefinition; public IdGeneratorResolverSecondPass( SimpleValue id, @@ -42,19 +41,33 @@ public class IdGeneratorResolverSecondPass implements SecondPass { this.buildingContext = buildingContext; } - public IdGeneratorResolverSecondPass( - SimpleValue id, - MemberDetails idAttributeMember, - String generatorType, - String generatorName, - MetadataBuildingContext buildingContext, - IdentifierGeneratorDefinition localIdentifierGeneratorDefinition) { - this( id, idAttributeMember, generatorType, generatorName, buildingContext ); - this.localIdentifierGeneratorDefinition = localIdentifierGeneratorDefinition; - } +// public IdGeneratorResolverSecondPass( +// SimpleValue id, +// MemberDetails idAttributeMember, +// String generatorType, +// String generatorName, +// MetadataBuildingContext buildingContext, +// IdentifierGeneratorDefinition localIdentifierGeneratorDefinition) { +// this( id, idAttributeMember, generatorType, generatorName, buildingContext ); +// this.localIdentifierGeneratorDefinition = localIdentifierGeneratorDefinition; +// } @Override public void doSecondPass(Map idGeneratorDefinitionMap) throws MappingException { - makeIdGenerator( id, idAttributeMember, generatorType, generatorName, buildingContext, localIdentifierGeneratorDefinition ); +// makeIdGenerator( id, idAttributeMember, generatorType, generatorName, buildingContext, localIdentifierGeneratorDefinition ); + makeIdGenerator( id, idAttributeMember, generatorType, generatorName, buildingContext, null ); } + +// public static void makeIdGenerator( +// SimpleValue id, +// MemberDetails idAttributeMember, +// String generatorType, +// String generatorName, +// MetadataBuildingContext buildingContext, +// IdentifierGeneratorDefinition foreignKGeneratorDefinition) { +// makeIdGenerator( id, idAttributeMember, generatorType, generatorName, buildingContext, +// foreignKGeneratorDefinition != null +// ? Map.of( foreignKGeneratorDefinition.getName(), foreignKGeneratorDefinition ) +// : null ); +// } } 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 c12422125b..199f7a1730 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 @@ -9,7 +9,6 @@ package org.hibernate.boot.model.internal; import java.lang.annotation.Annotation; import java.util.EnumSet; import java.util.List; -import java.util.Locale; import java.util.Map; import org.hibernate.AnnotationException; @@ -18,7 +17,6 @@ import org.hibernate.MappingException; import org.hibernate.annotations.Any; import org.hibernate.annotations.AttributeBinderType; import org.hibernate.annotations.CompositeType; -import org.hibernate.annotations.IdGeneratorType; import org.hibernate.annotations.Immutable; import org.hibernate.annotations.Index; import org.hibernate.annotations.LazyGroup; @@ -26,7 +24,6 @@ import org.hibernate.annotations.ManyToAny; import org.hibernate.annotations.NaturalId; import org.hibernate.annotations.OptimisticLock; import org.hibernate.annotations.Parent; -import org.hibernate.annotations.ValueGenerationType; import org.hibernate.binder.AttributeBinder; import org.hibernate.boot.model.IdentifierGeneratorDefinition; import org.hibernate.boot.model.naming.Identifier; @@ -47,7 +44,6 @@ import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.util.collections.CollectionHelper; import org.hibernate.mapping.Collection; import org.hibernate.mapping.Component; -import org.hibernate.mapping.GeneratorCreator; import org.hibernate.mapping.Join; import org.hibernate.mapping.KeyValue; import org.hibernate.mapping.MappedSuperclass; @@ -90,17 +86,14 @@ import static org.hibernate.boot.model.internal.BinderHelper.getMappedSuperclass import static org.hibernate.boot.model.internal.BinderHelper.getPath; import static org.hibernate.boot.model.internal.BinderHelper.getPropertyOverriddenByMapperOrMapsId; import static org.hibernate.boot.model.internal.BinderHelper.hasToOneAnnotation; -import static org.hibernate.boot.model.internal.BinderHelper.isCompositeId; import static org.hibernate.boot.model.internal.ClassPropertyHolder.handleGenericComponentProperty; import static org.hibernate.boot.model.internal.ClassPropertyHolder.prepareActualProperty; import static org.hibernate.boot.model.internal.CollectionBinder.bindCollection; import static org.hibernate.boot.model.internal.EmbeddableBinder.createCompositeBinder; import static org.hibernate.boot.model.internal.EmbeddableBinder.createEmbeddable; import static org.hibernate.boot.model.internal.EmbeddableBinder.isEmbedded; -import static org.hibernate.boot.model.internal.GeneratorBinder.beanContainer; -import static org.hibernate.boot.model.internal.GeneratorBinder.createIdGenerator; -import static org.hibernate.boot.model.internal.GeneratorBinder.generatorCreator; -import static org.hibernate.boot.model.internal.GeneratorBinder.identifierGeneratorCreator; +import static org.hibernate.boot.model.internal.GeneratorBinder.createIdGeneratorsFromGeneratorAnnotations; +import static org.hibernate.boot.model.internal.GeneratorBinder.createValueGeneratorFromAnnotations; import static org.hibernate.boot.model.internal.TimeZoneStorageHelper.resolveTimeZoneStorageCompositeUserType; import static org.hibernate.boot.model.internal.ToOneBinder.bindManyToOne; import static org.hibernate.boot.model.internal.ToOneBinder.bindOneToOne; @@ -449,35 +442,12 @@ public class PropertyBinder { } private void handleValueGeneration(Property property) { - if ( this.memberDetails != null ) { - property.setValueGeneratorCreator( getValueGenerationFromAnnotations( this.memberDetails ) ); + if ( memberDetails != null ) { + property.setValueGeneratorCreator( + createValueGeneratorFromAnnotations( holder, name, memberDetails, buildingContext ) ); } } - /** - * Returns the value generation strategy for the given property, if any. - */ - private GeneratorCreator getValueGenerationFromAnnotations(MemberDetails property) { - GeneratorCreator creator = null; - final List metaAnnotatedTargets = property.getMetaAnnotated( - ValueGenerationType.class, - getSourceModelContext() - ); - for ( Annotation metaAnnotatedTarget : metaAnnotatedTargets ) { - final GeneratorCreator candidate = generatorCreator( property, metaAnnotatedTarget, beanContainer( buildingContext ) ); - if ( candidate != null ) { - if ( creator != null ) { - throw new AnnotationException( "Property '" + qualify( holder.getPath(), name ) - + "' has multiple '@ValueGenerationType' annotations" ); - } - else { - creator = candidate; - } - } - } - return creator; - } - private void handleLob(Property property) { if ( this.memberDetails != null ) { // HHH-4635 -- needed for dialect-specific property ordering @@ -1181,12 +1151,15 @@ public class PropertyBinder { } else if ( propertyBinder.isId() ) { //components and regular basic types create SimpleValue objects - processId( + if ( isIdentifierMapper ) { + throw new AnnotationException( "Property '"+ getPath( propertyHolder, inferredData ) + + "' belongs to an '@IdClass' and may not be annotated '@Id' or '@EmbeddedId'" ); + } + createIdGeneratorsFromGeneratorAnnotations( propertyHolder, inferredData, (SimpleValue) propertyBinder.getValue(), classGenerators, - isIdentifierMapper, context ); } @@ -1457,71 +1430,4 @@ public class PropertyBinder { return null; } - - private static void processId( - PropertyHolder propertyHolder, - PropertyData inferredData, - SimpleValue idValue, - Map classGenerators, - boolean isIdentifierMapper, - MetadataBuildingContext context) { - if ( isIdentifierMapper ) { - throw new AnnotationException( "Property '"+ getPath( propertyHolder, inferredData ) - + "' belongs to an '@IdClass' and may not be annotated '@Id' or '@EmbeddedId'" ); - } - - final SourceModelBuildingContext sourceModelContext = context.getMetadataCollector().getSourceModelBuildingContext(); - final MemberDetails idAttributeMember = inferredData.getAttributeMember(); - final List idGeneratorAnnotations = idAttributeMember.getMetaAnnotated( IdGeneratorType.class, sourceModelContext ); - final List generatorAnnotations = idAttributeMember.getMetaAnnotated( ValueGenerationType.class, sourceModelContext ); - removeIdGenerators( generatorAnnotations, idGeneratorAnnotations ); - if ( idGeneratorAnnotations.size() + generatorAnnotations.size() > 1 ) { - throw new AnnotationException( String.format( - Locale.ROOT, - "Property `%s` has too many generator annotations : %s", - getPath( propertyHolder, inferredData ), - CollectionHelper.combineUntyped( idGeneratorAnnotations, generatorAnnotations ) - ) ); - } - if ( !idGeneratorAnnotations.isEmpty() ) { - idValue.setCustomIdGeneratorCreator( identifierGeneratorCreator( - idAttributeMember, - idGeneratorAnnotations.get(0), - idValue, - beanContainer( context ) - ) ); - } - else if ( !generatorAnnotations.isEmpty() ) { -// idValue.setCustomGeneratorCreator( generatorCreator( idAttributeMember, generatorAnnotation ) ); - throw new AnnotationException( String.format( - Locale.ROOT, - "Property '%s' is annotated `%s` which is not an `@IdGeneratorType`", - getPath( propertyHolder, inferredData ), - generatorAnnotations.get(0).annotationType() - ) ); - } - else { - final ClassDetails entityClass = inferredData.getClassOrElementType().determineRawClass(); - createIdGenerator( idValue, classGenerators, context, entityClass, idAttributeMember ); - if ( LOG.isTraceEnabled() ) { - LOG.tracev( - "Bind {0} on {1}", - isCompositeId( entityClass, idAttributeMember ) ? "@EmbeddedId" : "@Id", - inferredData.getPropertyName() - ); - } - } - } - - // Since these collections may contain Proxies created by common-annotations module we cannot reliably use simple remove/removeAll - // collection methods as those proxies do not implement hashcode/equals and even a simple `a.equals(a)` will return `false`. - // Instead, we will check the annotation types, since generator annotations should not be "repeatable" we should have only - // at most one annotation for a generator: - private static void removeIdGenerators( - List generatorAnnotations, - List idGeneratorAnnotations) { - for ( Annotation id : idGeneratorAnnotations ) { - generatorAnnotations.removeIf( gen -> gen.annotationType().equals( id.annotationType() ) ); - } - } } diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/ToOneBinder.java b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/ToOneBinder.java index 59d6b6aa53..7768dc0864 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/ToOneBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/ToOneBinder.java @@ -194,7 +194,7 @@ public class ToOneBinder { // This is a @OneToOne mapped to a physical o.h.mapping.ManyToOne value.markAsLogicalOneToOne(); } - value.setReferencedEntityName( getReferenceEntityName( inferredData, targetEntity, context ) ); + value.setReferencedEntityName( getReferenceEntityName( inferredData, targetEntity ) ); final MemberDetails property = inferredData.getAttributeMember(); defineFetchingStrategy( value, property, inferredData, propertyHolder ); //value.setFetchMode( fetchMode ); @@ -231,7 +231,7 @@ public class ToOneBinder { value, joinColumns, unique, - isTargetAnnotatedEntity( targetEntity, property, context ), + isTargetAnnotatedEntity( targetEntity, property ), propertyHolder.getPersistentClass(), fullPath, context @@ -257,8 +257,8 @@ public class ToOneBinder { ); } - static boolean isTargetAnnotatedEntity(ClassDetails targetEntity, MemberDetails property, MetadataBuildingContext context) { - final ClassDetails target = isDefault( targetEntity, context ) ? property.getType().determineRawClass() : targetEntity; + static boolean isTargetAnnotatedEntity(ClassDetails targetEntity, MemberDetails property) { + final ClassDetails target = isDefault( targetEntity ) ? property.getType().determineRawClass() : targetEntity; return target.hasDirectAnnotationUsage( Entity.class ); } @@ -535,8 +535,8 @@ public class ToOneBinder { propertyHolder.getEntityName(), propertyHolder, inferredData, - getReferenceEntityName( inferredData, targetEntity, context ), - isTargetAnnotatedEntity( targetEntity, annotatedProperty, context ), + getReferenceEntityName( inferredData, targetEntity ), + isTargetAnnotatedEntity( targetEntity, annotatedProperty ), notFoundAction, cascadeOnDelete, optional, @@ -653,14 +653,14 @@ public class ToOneBinder { } } - public static String getReferenceEntityName(PropertyData propertyData, ClassDetails targetEntity, MetadataBuildingContext context) { - return isDefault( targetEntity, context ) + public static String getReferenceEntityName(PropertyData propertyData, ClassDetails targetEntity) { + return isDefault( targetEntity ) ? propertyData.getClassOrElementName() : targetEntity.getName(); } public static String getReferenceEntityName(PropertyData propertyData, MetadataBuildingContext context) { - return getReferenceEntityName( propertyData, getTargetEntity( propertyData, context ), context ); + return getReferenceEntityName( propertyData, getTargetEntity( propertyData, context ) ); } public static ClassDetails getTargetEntity(PropertyData propertyData, MetadataBuildingContext context) { diff --git a/hibernate-core/src/main/java/org/hibernate/id/IdentifierGeneratorHelper.java b/hibernate-core/src/main/java/org/hibernate/id/IdentifierGeneratorHelper.java index f4a76d084f..3179f3d575 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/IdentifierGeneratorHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/id/IdentifierGeneratorHelper.java @@ -24,7 +24,6 @@ import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.generator.values.internal.GeneratedValuesHelper; import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.internal.util.StringHelper; import org.hibernate.metamodel.mapping.JdbcMapping; import org.hibernate.metamodel.mapping.SqlTypedMapping; import org.hibernate.metamodel.model.domain.NavigableRole; @@ -34,6 +33,7 @@ import org.hibernate.type.Type; import org.hibernate.type.descriptor.WrapperOptions; import static org.hibernate.engine.internal.ForeignKeys.getEntityIdentifierIfNotUnsaved; +import static org.hibernate.internal.util.StringHelper.unquote; import static org.hibernate.spi.NavigablePath.IDENTIFIER_MAPPER_PROPERTY; /** @@ -124,7 +124,7 @@ public final class IdentifierGeneratorHelper { private static boolean equal(String keyColumnName, String alias, Dialect dialect) { return alias.equalsIgnoreCase( keyColumnName ) - || alias.equalsIgnoreCase( StringHelper.unquote( keyColumnName, dialect ) ); + || alias.equalsIgnoreCase( unquote( keyColumnName, dialect ) ); } public static IntegralDataTypeHolder getIntegralDataTypeHolder(Class integralType) { diff --git a/hibernate-core/src/main/java/org/hibernate/id/IncrementGenerator.java b/hibernate-core/src/main/java/org/hibernate/id/IncrementGenerator.java index 37f11d4760..e870faf4a4 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/IncrementGenerator.java +++ b/hibernate-core/src/main/java/org/hibernate/id/IncrementGenerator.java @@ -15,7 +15,7 @@ import java.util.Properties; import org.hibernate.HibernateException; import org.hibernate.MappingException; -import org.hibernate.boot.model.naming.ObjectNameNormalizer; +import org.hibernate.boot.model.naming.Identifier; import org.hibernate.boot.model.relational.QualifiedTableName; import org.hibernate.boot.model.relational.SqlStringGenerationContext; import org.hibernate.dialect.Dialect; @@ -29,10 +29,10 @@ import org.hibernate.type.Type; import static org.hibernate.id.IdentifierGeneratorHelper.getIntegralDataTypeHolder; import static org.hibernate.id.PersistentIdentifierGenerator.CATALOG; -import static org.hibernate.id.PersistentIdentifierGenerator.IDENTIFIER_NORMALIZER; import static org.hibernate.id.PersistentIdentifierGenerator.PK; import static org.hibernate.id.PersistentIdentifierGenerator.SCHEMA; import static org.hibernate.internal.util.StringHelper.split; +import static org.hibernate.internal.util.config.ConfigurationHelper.getString; /** * An {@link IdentifierGenerator} that returns a {@code long}, constructed by counting @@ -89,18 +89,17 @@ public class IncrementGenerator implements IdentifierGenerator { returnClass = type.getReturnedClass(); final JdbcEnvironment jdbcEnvironment = serviceRegistry.requireService( JdbcEnvironment.class ); - final ObjectNameNormalizer normalizer = (ObjectNameNormalizer) parameters.get( IDENTIFIER_NORMALIZER ); + final IdentifierHelper identifierHelper = jdbcEnvironment.getIdentifierHelper(); column = parameters.getProperty( COLUMN ); if ( column == null ) { column = parameters.getProperty( PK ); } - column = normalizer.normalizeIdentifierQuoting( column ).render( jdbcEnvironment.getDialect() ); + column = identifierHelper.normalizeQuoting( identifierHelper.toIdentifier( column ) ) + .render( jdbcEnvironment.getDialect() ); - IdentifierHelper identifierHelper = jdbcEnvironment.getIdentifierHelper(); - - final String schema = normalizer.toDatabaseIdentifierText( parameters.getProperty( SCHEMA ) ); - final String catalog = normalizer.toDatabaseIdentifierText( parameters.getProperty( CATALOG ) ); + final Identifier catalog = identifierHelper.toIdentifier( getString( CATALOG, parameters ) ); + final Identifier schema = identifierHelper.toIdentifier( getString( SCHEMA, parameters ) ); String tableList = parameters.getProperty( TABLES ); if ( tableList == null ) { @@ -108,8 +107,7 @@ public class IncrementGenerator implements IdentifierGenerator { } physicalTableNames = new ArrayList<>(); for ( String tableName : split( ", ", tableList ) ) { - physicalTableNames.add( new QualifiedTableName( identifierHelper.toIdentifier( catalog ), - identifierHelper.toIdentifier( schema ), identifierHelper.toIdentifier( tableName ) ) ); + physicalTableNames.add( new QualifiedTableName( catalog, schema, identifierHelper.toIdentifier( tableName ) ) ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/id/PersistentIdentifierGenerator.java b/hibernate-core/src/main/java/org/hibernate/id/PersistentIdentifierGenerator.java index 312a74cb76..079826489c 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/PersistentIdentifierGenerator.java +++ b/hibernate-core/src/main/java/org/hibernate/id/PersistentIdentifierGenerator.java @@ -53,7 +53,10 @@ public interface PersistentIdentifierGenerator extends OptimizableGenerator { /** * The key under which to find the {@link org.hibernate.boot.model.naming.ObjectNameNormalizer} in the config param map. + * + * @deprecated no longer set, use {@link org.hibernate.engine.jdbc.env.spi.JdbcEnvironment#getIdentifierHelper} */ + @Deprecated(since = "7.0", forRemoval = true) String IDENTIFIER_NORMALIZER = "identifier_normalizer"; /** diff --git a/hibernate-core/src/main/java/org/hibernate/internal/util/collections/CollectionHelper.java b/hibernate-core/src/main/java/org/hibernate/internal/util/collections/CollectionHelper.java index a49d3bc637..e89ff2b559 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/util/collections/CollectionHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/util/collections/CollectionHelper.java @@ -6,7 +6,6 @@ */ package org.hibernate.internal.util.collections; -import java.lang.reflect.Array; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/id/SequenceStyleGeneratorBehavesLikeSequeceHiloGeneratorWitZeroIncrementSizeTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/id/SequenceStyleGeneratorBehavesLikeSequeceHiloGeneratorWitZeroIncrementSizeTest.java index 69915702c9..367da7e571 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/id/SequenceStyleGeneratorBehavesLikeSequeceHiloGeneratorWitZeroIncrementSizeTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/id/SequenceStyleGeneratorBehavesLikeSequeceHiloGeneratorWitZeroIncrementSizeTest.java @@ -18,7 +18,6 @@ import org.hibernate.cfg.AvailableSettings; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor; -import org.hibernate.id.PersistentIdentifierGenerator; import org.hibernate.id.enhanced.SequenceStyleGenerator; import org.hibernate.type.StandardBasicTypes; @@ -63,10 +62,6 @@ public class SequenceStyleGeneratorBehavesLikeSequeceHiloGeneratorWitZeroIncreme properties.setProperty( SequenceStyleGenerator.SEQUENCE_PARAM, TEST_SEQUENCE ); properties.setProperty( SequenceStyleGenerator.OPT_PARAM, "legacy-hilo" ); properties.setProperty( SequenceStyleGenerator.INCREMENT_PARAM, "0" ); // JPA allocationSize of 1 - properties.put( - PersistentIdentifierGenerator.IDENTIFIER_NORMALIZER, - buildingContext.getObjectNameNormalizer() - ); generator.configure( buildingContext.getBootstrapContext() .getTypeConfiguration() diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/id/enhanced/SequenceStyleConfigUnitTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/id/enhanced/SequenceStyleConfigUnitTest.java index 37a9109369..9a32dd6d2a 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/id/enhanced/SequenceStyleConfigUnitTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/id/enhanced/SequenceStyleConfigUnitTest.java @@ -11,7 +11,6 @@ import java.util.Properties; import org.hibernate.boot.model.relational.Database; import org.hibernate.boot.model.relational.internal.SqlStringGenerationContextImpl; import org.hibernate.boot.registry.StandardServiceRegistry; -import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.boot.spi.MetadataBuildingContext; import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.Environment; @@ -96,10 +95,6 @@ public class SequenceStyleConfigUnitTest { private Properties buildGeneratorPropertiesBase(MetadataBuildingContext buildingContext) { Properties props = new Properties(); - props.put( - PersistentIdentifierGenerator.IDENTIFIER_NORMALIZER, - buildingContext.getObjectNameNormalizer() - ); props.put( PersistentIdentifierGenerator.IMPLICIT_NAME_BASE, "ID"