From c8c92cfcbf9db8a02eb9937f471257f24779d507 Mon Sep 17 00:00:00 2001 From: Gavin King Date: Sat, 18 May 2024 22:43:41 +0200 Subject: [PATCH] HHH-18139 isolate generator creation in GeneratorBinder Signed-off-by: Gavin King --- .../boot/model/internal/AnnotationBinder.java | 14 +- .../boot/model/internal/GeneratorBinder.java | 359 ++++++++++++++---- .../source/internal/hbm/ModelBinder.java | 57 +-- .../internal/IdentifierGeneratorUtil.java | 218 ----------- .../org/hibernate/mapping/SimpleValue.java | 4 +- 5 files changed, 309 insertions(+), 343 deletions(-) delete mode 100644 hibernate-core/src/main/java/org/hibernate/id/factory/internal/IdentifierGeneratorUtil.java 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 e194a0c757..686dc57ede 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 @@ -58,6 +58,8 @@ 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.GeneratorBinder.buildSequenceIdGenerator; +import static org.hibernate.boot.model.internal.GeneratorBinder.buildTableIdGenerator; 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; @@ -155,16 +157,16 @@ public static void bindPackage(ClassLoaderService cls, String packageName, Metad } private static void handleIdGenerators(ClassDetails packageInfoClassDetails, MetadataBuildingContext context) { - packageInfoClassDetails.forEachAnnotationUsage( SequenceGenerator.class, (usage) -> { - IdentifierGeneratorDefinition idGen = buildIdGenerator( usage, context ); + packageInfoClassDetails.forEachAnnotationUsage( SequenceGenerator.class, usage -> { + IdentifierGeneratorDefinition idGen = buildSequenceIdGenerator( usage ); context.getMetadataCollector().addIdentifierGenerator( idGen ); if ( LOG.isTraceEnabled() ) { LOG.tracev( "Add sequence generator with name: {0}", idGen.getName() ); } } ); - packageInfoClassDetails.forEachAnnotationUsage( TableGenerator.class, (usage) -> { - IdentifierGeneratorDefinition idGen = buildIdGenerator( usage, context ); + packageInfoClassDetails.forEachAnnotationUsage( TableGenerator.class, usage -> { + IdentifierGeneratorDefinition idGen = buildTableIdGenerator( usage ); context.getMetadataCollector().addIdentifierGenerator( idGen ); if ( LOG.isTraceEnabled() ) { LOG.tracev( "Add table generator with name: {0}", idGen.getName() ); @@ -173,13 +175,13 @@ private static void handleIdGenerators(ClassDetails packageInfoClassDetails, Met } private static void bindGenericGenerators(AnnotationTarget annotatedElement, MetadataBuildingContext context) { - annotatedElement.forEachAnnotationUsage( GenericGenerator.class, (usage) -> { + annotatedElement.forEachAnnotationUsage( GenericGenerator.class, usage -> { bindGenericGenerator( usage, context ); } ); } private static void bindGenericGenerator(AnnotationUsage def, MetadataBuildingContext context) { - context.getMetadataCollector().addIdentifierGenerator( buildIdGenerator( def, context ) ); + context.getMetadataCollector().addIdentifierGenerator( buildIdGenerator( def ) ); } public static void bindQueries(AnnotationTarget annotationTarget, MetadataBuildingContext context) { 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 2299940e5a..8706e0318b 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 @@ -7,13 +7,14 @@ package org.hibernate.boot.model.internal; import java.lang.annotation.Annotation; +import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Member; import java.util.HashMap; import java.util.Map; +import java.util.Properties; import org.hibernate.AnnotationException; -import org.hibernate.AssertionFailure; import org.hibernate.HibernateException; import org.hibernate.MappingException; import org.hibernate.annotations.GenericGenerator; @@ -22,22 +23,43 @@ 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.boot.spi.PropertyData; +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.generator.AnnotationBasedGenerator; import org.hibernate.generator.BeforeExecutionGenerator; import org.hibernate.generator.Generator; import org.hibernate.generator.GeneratorCreationContext; import org.hibernate.generator.OnExecutionGenerator; +import org.hibernate.id.Assigned; 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.id.factory.spi.CustomIdGeneratorCreationContext; import org.hibernate.internal.CoreLogging; +import org.hibernate.mapping.Column; import org.hibernate.mapping.GeneratorCreator; import org.hibernate.mapping.IdentifierGeneratorCreator; +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.AnnotationUsage; import org.hibernate.models.spi.ClassDetails; @@ -58,13 +80,186 @@ 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.isGlobalGeneratorNameGlobal; -import static org.hibernate.id.factory.internal.IdentifierGeneratorUtil.collectParameters; +import static org.hibernate.internal.util.ReflectHelper.getDefaultConstructor; +import static org.hibernate.internal.util.StringHelper.isNotEmpty; import static org.hibernate.mapping.SimpleValue.DEFAULT_ID_GEN_STRATEGY; public class GeneratorBinder { private static final Logger LOG = CoreLogging.logger( BinderHelper.class ); + public static Generator createLegacyIdentifierGenerator( + SimpleValue simpleValue, + Dialect dialect, + String defaultCatalog, + String defaultSchema, + RootClass rootClass) { + final Class generatorClass = generatorClass( simpleValue ); + final Constructor defaultConstructor = getDefaultConstructor( generatorClass ); + if ( defaultConstructor == null ) { + throw new org.hibernate.InstantiationException( "No default constructor for id generator class", generatorClass ); + } + final Generator identifierGenerator; + try { + identifierGenerator = defaultConstructor.newInstance(); + } + catch (Exception e) { + throw new org.hibernate.InstantiationException( "Could not instantiate id generator", generatorClass, e ); + } + if ( identifierGenerator instanceof Configurable ) { + final Properties parameters = collectParameters( simpleValue, dialect, defaultCatalog, defaultSchema, rootClass ); + final Configurable configurable = (Configurable) identifierGenerator; + configurable.configure( simpleValue.getType(), parameters, simpleValue.getServiceRegistry() ); + } + return identifierGenerator; + } + + private static Class generatorClass(SimpleValue simpleValue) { + String strategy = simpleValue.getIdentifierGeneratorStrategy(); + if ( "native".equals(strategy) ) { + strategy = + simpleValue.getMetadata().getDatabase().getDialect() + .getNativeIdentifierGeneratorStrategy(); + } + switch (strategy) { + case "assigned": + return 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 = + simpleValue.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; + } + + public static Properties collectParameters( + SimpleValue simpleValue, + Dialect dialect, + String defaultCatalog, + String defaultSchema, + RootClass rootClass) { + final ConfigurationService configService = + simpleValue.getMetadata().getMetadataBuildingOptions().getServiceRegistry() + .requireService( ConfigurationService.class ); + + final Properties params = new Properties(); + + // This is for backwards compatibility only; + // when this method is called by Hibernate ORM, defaultSchema and defaultCatalog are always + // null, and defaults are handled later. + if ( defaultSchema != null ) { + params.setProperty( PersistentIdentifierGenerator.SCHEMA, defaultSchema); + } + + if ( defaultCatalog != null ) { + params.setProperty( PersistentIdentifierGenerator.CATALOG, defaultCatalog); + } + + // 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 = simpleValue.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) simpleValue.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, + simpleValue.getTable().isSubselect() + ? rootClass.getJpaEntityName() + : simpleValue.getTable().getName() ); + + params.setProperty( PersistentIdentifierGenerator.TABLES, + identityTablesString( dialect, rootClass ) ); + } + else { + params.setProperty( PersistentIdentifierGenerator.TABLES, tableName ); + params.setProperty( OptimizableGenerator.IMPLICIT_NAME_BASE, tableName ); + } + + if ( simpleValue.getIdentifierGeneratorParameters() != null ) { + params.putAll( simpleValue.getIdentifierGeneratorParameters() ); + } + + // TODO : we should pass along all settings once "config lifecycle" is hashed out... + + params.put( IdentifierGenerator.CONTRIBUTOR_NAME, + simpleValue.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 ) ); + } + + 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.length()>0 ) { + 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. @@ -79,8 +274,6 @@ public static void makeIdGenerator( LOG.debugf( "#makeIdGenerator(%s, %s, %s, %s, ...)", id, idAttributeMember, generatorType, generatorName ); //generator settings - id.setIdentifierGeneratorStrategy( generatorType ); - final Map parameters = new HashMap<>(); //always settable @@ -95,12 +288,8 @@ public static void makeIdGenerator( if ( !generatorName.isEmpty() ) { //we have a named generator - final IdentifierGeneratorDefinition definition = makeIdentifierGeneratorDefinition( - generatorName, - idAttributeMember, - localGenerators, - buildingContext - ); + final IdentifierGeneratorDefinition definition = + makeIdentifierGeneratorDefinition( generatorName, idAttributeMember, localGenerators, buildingContext ); if ( definition == null ) { throw new AnnotationException( "No id generator was declared with the name '" + generatorName + "' specified by '@GeneratedValue'" @@ -109,21 +298,20 @@ public static void makeIdGenerator( //This is quite vague in the spec but a generator could override the generator choice final String identifierGeneratorStrategy = definition.getStrategy(); //yuk! this is a hack not to override 'AUTO' even if generator is set - final boolean avoidOverriding = identifierGeneratorStrategy.equals( "identity" ) + final boolean avoidOverriding = + identifierGeneratorStrategy.equals( "identity" ) || identifierGeneratorStrategy.equals( "seqhilo" ); if ( generatorType == null || !avoidOverriding ) { - id.setIdentifierGeneratorStrategy( identifierGeneratorStrategy ); - if ( DEFAULT_ID_GEN_STRATEGY.equals( identifierGeneratorStrategy ) ) { - id.setNullValue( "undefined" ); - } + generatorType = identifierGeneratorStrategy; } //checkIfMatchingGenerator(definition, generatorType, generatorName); parameters.putAll( definition.getParameters() ); } + id.setIdentifierGeneratorStrategy( generatorType ); + id.setIdentifierGeneratorParameters( parameters ); if ( DEFAULT_ID_GEN_STRATEGY.equals( generatorType ) ) { id.setNullValue( "undefined" ); } - id.setIdentifierGeneratorParameters( parameters ); } /** @@ -191,23 +379,20 @@ public static Map buildGenerators( final InFlightMetadataCollector metadataCollector = context.getMetadataCollector(); final Map generators = new HashMap<>(); - annotatedElement.forEachAnnotationUsage( TableGenerator.class, (usage) -> { - IdentifierGeneratorDefinition idGenerator = buildIdGenerator( usage, context ); - generators.put( - idGenerator.getName(), - idGenerator - ); - metadataCollector.addIdentifierGenerator( idGenerator ); - } ); - - annotatedElement.forEachAnnotationUsage( SequenceGenerator.class, (usage) -> { - IdentifierGeneratorDefinition idGenerator = buildIdGenerator( usage, context ); + annotatedElement.forEachAnnotationUsage( TableGenerator.class, usage -> { + IdentifierGeneratorDefinition idGenerator = buildTableIdGenerator( usage ); generators.put( idGenerator.getName(), idGenerator ); metadataCollector.addIdentifierGenerator( idGenerator ); } ); - annotatedElement.forEachAnnotationUsage( GenericGenerator.class, (usage) -> { - final IdentifierGeneratorDefinition idGenerator = buildIdGenerator( usage, context ); + annotatedElement.forEachAnnotationUsage( SequenceGenerator.class, usage -> { + IdentifierGeneratorDefinition idGenerator = buildSequenceIdGenerator( usage ); + generators.put( idGenerator.getName(), idGenerator ); + metadataCollector.addIdentifierGenerator( idGenerator ); + } ); + + annotatedElement.forEachAnnotationUsage( GenericGenerator.class, usage -> { + final IdentifierGeneratorDefinition idGenerator = buildIdGenerator( usage ); generators.put( idGenerator.getName(), idGenerator ); metadataCollector.addIdentifierGenerator( idGenerator ); } ); @@ -252,50 +437,50 @@ public String getGeneratedValueGeneratorName() { ); } - static IdentifierGeneratorDefinition buildIdGenerator( - AnnotationUsage generatorAnnotation, - MetadataBuildingContext context) { + static IdentifierGeneratorDefinition buildIdGenerator(AnnotationUsage generatorAnnotation) { if ( generatorAnnotation == null ) { return null; } final IdentifierGeneratorDefinition.Builder definitionBuilder = new IdentifierGeneratorDefinition.Builder(); - if ( TableGenerator.class.isAssignableFrom( generatorAnnotation.getAnnotationType() ) ) { - //noinspection unchecked - GenerationStrategyInterpreter.STRATEGY_INTERPRETER.interpretTableGenerator( - (AnnotationUsage) generatorAnnotation, - definitionBuilder - ); - if ( LOG.isTraceEnabled() ) { - LOG.tracev( "Add table generator with name: {0}", definitionBuilder.getName() ); - } + definitionBuilder.setName( generatorAnnotation.getString( "name" ) ); + final Class generatorClass = + generatorAnnotation.getClassDetails( "type" ).toJavaClass(); + final String strategy = generatorClass.equals(Generator.class) + ? generatorAnnotation.getString( "strategy" ) + : generatorClass.getName(); + definitionBuilder.setStrategy( strategy ); + definitionBuilder.addParams( extractParameterMap( generatorAnnotation.getList( "parameters" ) ) ); + if ( LOG.isTraceEnabled() ) { + LOG.tracev( "Add generic generator with name: {0}", definitionBuilder.getName() ); } - else if ( SequenceGenerator.class.isAssignableFrom( generatorAnnotation.getAnnotationType() ) ) { - //noinspection unchecked - GenerationStrategyInterpreter.STRATEGY_INTERPRETER.interpretSequenceGenerator( - (AnnotationUsage) generatorAnnotation, - definitionBuilder - ); - if ( LOG.isTraceEnabled() ) { - LOG.tracev( "Add sequence generator with name: {0}", definitionBuilder.getName() ); - } + return definitionBuilder.build(); + } + + static IdentifierGeneratorDefinition buildTableIdGenerator(AnnotationUsage generatorAnnotation) { + if ( generatorAnnotation == null ) { + return null; } - else if ( GenericGenerator.class.isAssignableFrom( generatorAnnotation.getAnnotationType() ) ) { - //noinspection unchecked - final AnnotationUsage genericGenerator = (AnnotationUsage) generatorAnnotation; - definitionBuilder.setName( genericGenerator.getString( "name" ) ); - final Class generatorClass = genericGenerator.getClassDetails( "type" ).toJavaClass(); - final String strategy = generatorClass.equals(Generator.class) - ? genericGenerator.getString( "strategy" ) - : generatorClass.getName(); - definitionBuilder.setStrategy( strategy ); - definitionBuilder.addParams( extractParameterMap( genericGenerator.getList( "parameters" ) ) ); - if ( LOG.isTraceEnabled() ) { - LOG.tracev( "Add generic generator with name: {0}", definitionBuilder.getName() ); - } + + final IdentifierGeneratorDefinition.Builder definitionBuilder = new IdentifierGeneratorDefinition.Builder(); + GenerationStrategyInterpreter.STRATEGY_INTERPRETER + .interpretTableGenerator( generatorAnnotation, definitionBuilder ); + if ( LOG.isTraceEnabled() ) { + LOG.tracev( "Add table generator with name: {0}", definitionBuilder.getName() ); } - else { - throw new AssertionFailure( "Unknown Generator annotation: " + generatorAnnotation ); + return definitionBuilder.build(); + } + + static IdentifierGeneratorDefinition buildSequenceIdGenerator(AnnotationUsage generatorAnnotation) { + if ( generatorAnnotation == null ) { + return null; + } + + final IdentifierGeneratorDefinition.Builder definitionBuilder = new IdentifierGeneratorDefinition.Builder(); + GenerationStrategyInterpreter.STRATEGY_INTERPRETER + .interpretSequenceGenerator( generatorAnnotation, definitionBuilder ); + if ( LOG.isTraceEnabled() ) { + LOG.tracev( "Add sequence generator with name: {0}", definitionBuilder.getName() ); } return definitionBuilder.build(); } @@ -513,13 +698,14 @@ private static void checkVersionGenerationAlways(MemberDetails property, Generat private static void callConfigure(GeneratorCreationContext creationContext, Generator generator) { if ( generator instanceof Configurable ) { final Value value = creationContext.getProperty().getValue(); - ( (Configurable) generator ).configure( value.getType(), collectParameters( + Properties parameters = collectParameters( (SimpleValue) value, creationContext.getDatabase().getDialect(), creationContext.getDefaultCatalog(), creationContext.getDefaultSchema(), creationContext.getPersistentClass().getRootClass() - ), creationContext.getServiceRegistry() ); + ); + ( (Configurable) generator ).configure( value.getType(), parameters, creationContext.getServiceRegistry() ); } } @@ -571,4 +757,43 @@ static IdentifierGeneratorDefinition createForeignGenerator(PropertyData mapsIdP foreignGeneratorBuilder.addParam( "property", mapsIdProperty.getPropertyName() ); return foreignGeneratorBuilder.build(); } + + public static void makeIdentifier( + final MappingDocument sourceDocument, + IdentifierGeneratorDefinition generator, + String unsavedValue, + SimpleValue identifierValue, + MetadataBuildingContext buildingContext) { + if ( generator != null ) { + final Map params = new HashMap<>(); + + // see if the specified generator name matches a registered + String generatorName = generator.getStrategy(); + final IdentifierGeneratorDefinition generatorDef = + sourceDocument.getMetadataCollector().getIdentifierGenerator( generatorName ); + if ( generatorDef != null ) { + generatorName = generatorDef.getStrategy(); + params.putAll( generatorDef.getParameters() ); + } + + // YUCK! but cannot think of a clean way to do this given the string-config based scheme + params.put( PersistentIdentifierGenerator.IDENTIFIER_NORMALIZER, + buildingContext.getObjectNameNormalizer() ); + + params.putAll( generator.getParameters() ); + + identifierValue.setIdentifierGeneratorStrategy( generatorName ); + identifierValue.setIdentifierGeneratorParameters( params ); + } + + if ( isNotEmpty( unsavedValue ) ) { + identifierValue.setNullValue( unsavedValue ); + } + else if ( DEFAULT_ID_GEN_STRATEGY.equals( identifierValue.getIdentifierGeneratorStrategy() ) ) { + identifierValue.setNullValue( "undefined" ); + } + else { + identifierValue.setNullValue( null ); + } + } } diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/source/internal/hbm/ModelBinder.java b/hibernate-core/src/main/java/org/hibernate/boot/model/source/internal/hbm/ModelBinder.java index abba520074..269c272407 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/model/source/internal/hbm/ModelBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/model/source/internal/hbm/ModelBinder.java @@ -41,7 +41,6 @@ import org.hibernate.boot.model.naming.ImplicitMapKeyColumnNameSource; import org.hibernate.boot.model.naming.ImplicitNamingStrategy; import org.hibernate.boot.model.naming.ImplicitUniqueKeyNameSource; -import org.hibernate.boot.model.naming.ObjectNameNormalizer; import org.hibernate.boot.model.relational.Database; import org.hibernate.boot.model.relational.Namespace; import org.hibernate.boot.model.source.internal.ImplicitColumnNamingSecondPass; @@ -108,7 +107,6 @@ import org.hibernate.engine.spi.FilterDefinition; import org.hibernate.generator.internal.GeneratedGeneration; import org.hibernate.generator.internal.SourceGeneration; -import org.hibernate.id.PersistentIdentifierGenerator; import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.util.StringHelper; @@ -162,6 +160,7 @@ import org.hibernate.usertype.ParameterizedType; import org.hibernate.usertype.UserType; +import static org.hibernate.boot.model.internal.GeneratorBinder.makeIdentifier; import static org.hibernate.boot.model.naming.Identifier.toIdentifier; import static org.hibernate.boot.model.source.internal.hbm.Helper.reflectedPropertyClass; import static org.hibernate.cfg.AvailableSettings.USE_ENTITY_WHERE_CLAUSE_FOR_COLLECTIONS; @@ -169,7 +168,6 @@ import static org.hibernate.internal.util.StringHelper.getNonEmptyOrConjunctionIfBothNonEmpty; import static org.hibernate.internal.util.StringHelper.isNotEmpty; import static org.hibernate.internal.util.collections.CollectionHelper.isEmpty; -import static org.hibernate.mapping.SimpleValue.DEFAULT_ID_GEN_STRATEGY; /** * Responsible for coordinating the binding of all information inside entity tags ({@code }, etc). @@ -182,7 +180,6 @@ public class ModelBinder { private final MetadataBuildingContext metadataBuildingContext; private final Database database; - private final ObjectNameNormalizer objectNameNormalizer; private final ImplicitNamingStrategy implicitNamingStrategy; private final RelationalObjectBinder relationalObjectBinder; @@ -194,12 +191,6 @@ public ModelBinder(final MetadataBuildingContext context) { this.metadataBuildingContext = context; this.database = context.getMetadataCollector().getDatabase(); - this.objectNameNormalizer = new ObjectNameNormalizer() { - @Override - protected MetadataBuildingContext getBuildingContext() { - return context; - } - }; this.implicitNamingStrategy = context.getBuildingOptions().getImplicitNamingStrategy(); this.relationalObjectBinder = new RelationalObjectBinder( context ); } @@ -752,47 +743,11 @@ public MetadataBuildingContext getBuildingContext() { sourceDocument, idSource.getIdentifierGeneratorDescriptor(), idSource.getUnsavedValue(), - idValue + idValue, + metadataBuildingContext ); } - private void makeIdentifier( - final MappingDocument sourceDocument, - IdentifierGeneratorDefinition generator, - String unsavedValue, - SimpleValue identifierValue) { - if ( generator != null ) { - final Map params = new HashMap<>(); - - // see if the specified generator name matches a registered - String generatorName = generator.getStrategy(); - final IdentifierGeneratorDefinition generatorDef = sourceDocument.getMetadataCollector() - .getIdentifierGenerator( generatorName ); - if ( generatorDef != null ) { - generatorName = generatorDef.getStrategy(); - params.putAll( generatorDef.getParameters() ); - } - identifierValue.setIdentifierGeneratorStrategy( generatorName ); - - // YUCK! but cannot think of a clean way to do this given the string-config based scheme - params.put( PersistentIdentifierGenerator.IDENTIFIER_NORMALIZER, objectNameNormalizer ); - - params.putAll( generator.getParameters() ); - - identifierValue.setIdentifierGeneratorParameters( params ); - } - - if ( isNotEmpty( unsavedValue ) ) { - identifierValue.setNullValue( unsavedValue ); - } - else if ( DEFAULT_ID_GEN_STRATEGY.equals( identifierValue.getIdentifierGeneratorStrategy() ) ) { - identifierValue.setNullValue( "undefined" ); - } - else { - identifierValue.setNullValue( null ); - } - } - private void bindAggregatedCompositeEntityIdentifier( MappingDocument mappingDocument, EntityHierarchySourceImpl hierarchySource, @@ -949,7 +904,8 @@ private void finishBindingCompositeIdentifier( sourceDocument, identifierSource.getIdentifierGeneratorDescriptor(), null, - cid + cid, + metadataBuildingContext ); } @@ -3348,7 +3304,8 @@ protected void bindCollectionIdentifier() { mappingDocument, new IdentifierGeneratorDefinition( idSource.getGeneratorName(), idSource.getParameters() ), null, - idBinding + idBinding, + metadataBuildingContext ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/id/factory/internal/IdentifierGeneratorUtil.java b/hibernate-core/src/main/java/org/hibernate/id/factory/internal/IdentifierGeneratorUtil.java deleted file mode 100644 index 772c464178..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/id/factory/internal/IdentifierGeneratorUtil.java +++ /dev/null @@ -1,218 +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.id.factory.internal; - -import org.hibernate.InstantiationException; -import org.hibernate.MappingException; -import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; -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.Assigned; -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.id.enhanced.TableGenerator; -import org.hibernate.mapping.Column; -import org.hibernate.mapping.RootClass; -import org.hibernate.mapping.SimpleValue; -import org.hibernate.mapping.Table; -import org.hibernate.generator.Generator; - -import java.lang.reflect.Constructor; -import java.util.Map; -import java.util.Properties; - -import static org.hibernate.internal.util.ReflectHelper.getDefaultConstructor; - -public class IdentifierGeneratorUtil { - - public static Generator createLegacyIdentifierGenerator( - SimpleValue simpleValue, - Dialect dialect, - String defaultCatalog, - String defaultSchema, - RootClass rootClass) { - final Class generatorClass = generatorClass( simpleValue ); - final Constructor defaultConstructor = getDefaultConstructor( generatorClass ); - if ( defaultConstructor == null ) { - throw new InstantiationException( "No default constructor for id generator class", generatorClass ); - } - final Generator identifierGenerator; - try { - identifierGenerator = defaultConstructor.newInstance(); - } - catch (Exception e) { - throw new InstantiationException( "Could not instantiate id generator", generatorClass, e ); - } - if ( identifierGenerator instanceof Configurable ) { - final Properties parameters = collectParameters( simpleValue, dialect, defaultCatalog, defaultSchema, rootClass ); - final Configurable configurable = (Configurable) identifierGenerator; - configurable.configure( simpleValue.getType(), parameters, simpleValue.getServiceRegistry() ); - } - return identifierGenerator; - } - - private static Class generatorClass(SimpleValue simpleValue) { - String strategy = simpleValue.getIdentifierGeneratorStrategy(); - if ( "native".equals(strategy) ) { - strategy = - simpleValue.getMetadata().getDatabase().getDialect() - .getNativeIdentifierGeneratorStrategy(); - } - switch (strategy) { - case "assigned": - return Assigned.class; - case "enhanced-sequence": - case "sequence": - return SequenceStyleGenerator.class; - case "enhanced-table": - case "table": - return 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 = - simpleValue.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; - } - - public static Properties collectParameters( - SimpleValue simpleValue, - Dialect dialect, - String defaultCatalog, - String defaultSchema, - RootClass rootClass) { - final ConfigurationService configService = - simpleValue.getMetadata().getMetadataBuildingOptions().getServiceRegistry() - .requireService( ConfigurationService.class ); - - final Properties params = new Properties(); - - // This is for backwards compatibility only; - // when this method is called by Hibernate ORM, defaultSchema and defaultCatalog are always - // null, and defaults are handled later. - if ( defaultSchema != null ) { - params.setProperty( PersistentIdentifierGenerator.SCHEMA, defaultSchema); - } - - if ( defaultCatalog != null ) { - params.setProperty( PersistentIdentifierGenerator.CATALOG, defaultCatalog); - } - - // 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 = simpleValue.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) simpleValue.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, - simpleValue.getTable().isSubselect() - ? rootClass.getJpaEntityName() - : simpleValue.getTable().getName() ); - - params.setProperty( PersistentIdentifierGenerator.TABLES, - identityTablesString( dialect, rootClass ) ); - } - else { - params.setProperty( PersistentIdentifierGenerator.TABLES, tableName ); - params.setProperty( OptimizableGenerator.IMPLICIT_NAME_BASE, tableName ); - } - - if ( simpleValue.getIdentifierGeneratorParameters() != null ) { - params.putAll( simpleValue.getIdentifierGeneratorParameters() ); - } - - // TODO : we should pass along all settings once "config lifecycle" is hashed out... - - params.put( IdentifierGenerator.CONTRIBUTOR_NAME, - simpleValue.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 ) ); - } - - 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.length()>0 ) { - 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; - } - } - -} diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/SimpleValue.java b/hibernate-core/src/main/java/org/hibernate/mapping/SimpleValue.java index d5cb6ce939..1274ef9e30 100644 --- a/hibernate-core/src/main/java/org/hibernate/mapping/SimpleValue.java +++ b/hibernate-core/src/main/java/org/hibernate/mapping/SimpleValue.java @@ -66,7 +66,7 @@ import static java.lang.Boolean.parseBoolean; import static org.hibernate.boot.model.convert.spi.ConverterDescriptor.TYPE_NAME_PREFIX; -import static org.hibernate.id.factory.internal.IdentifierGeneratorUtil.createLegacyIdentifierGenerator; +import static org.hibernate.boot.model.internal.GeneratorBinder.createLegacyIdentifierGenerator; import static org.hibernate.internal.util.collections.ArrayHelper.toBooleanArray; /** @@ -398,7 +398,7 @@ public Generator createGenerator(Dialect dialect, RootClass rootClass) throws Ma ); } else { - generator = createLegacyIdentifierGenerator(this, dialect, null, null, rootClass ); + generator = createLegacyIdentifierGenerator( this, dialect, null, null, rootClass ); if ( generator instanceof IdentityGenerator ) { setColumnToIdentity(); }