From 3c4a871da5ea8e385614a9f114d0cdc77eb8d750 Mon Sep 17 00:00:00 2001 From: Gavin King Date: Sat, 27 Sep 2025 17:51:33 +0200 Subject: [PATCH 1/6] misc cleanups in the legacy id package --- .../hibernate/id/AbstractUUIDGenerator.java | 8 ++- ...ompositeNestedGeneratedValueGenerator.java | 57 +++++++-------- .../java/org/hibernate/id/GUIDGenerator.java | 13 ++-- .../id/IdentifierGeneratorHelper.java | 72 ++++++++++--------- .../org/hibernate/id/IdentityGenerator.java | 10 +-- .../org/hibernate/id/IncrementGenerator.java | 30 ++++---- .../org/hibernate/id/NativeGenerator.java | 33 ++++----- 7 files changed, 109 insertions(+), 114 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/id/AbstractUUIDGenerator.java b/hibernate-core/src/main/java/org/hibernate/id/AbstractUUIDGenerator.java index f64e127f18a7..3de9b5a66211 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/AbstractUUIDGenerator.java +++ b/hibernate-core/src/main/java/org/hibernate/id/AbstractUUIDGenerator.java @@ -8,6 +8,8 @@ import org.hibernate.internal.util.BytesHelper; +import static java.lang.System.currentTimeMillis; + /** * The base class for identifier generators that use a UUID algorithm. This * class implements the algorithm, subclasses define the identifier @@ -34,7 +36,7 @@ public abstract class AbstractUUIDGenerator implements IdentifierGenerator { } private static short counter = (short) 0; - private static final int JVM = (int) ( System.currentTimeMillis() >>> 8 ); + private static final int JVM = (int) ( currentTimeMillis() >>> 8 ); public AbstractUUIDGenerator() { } @@ -72,10 +74,10 @@ protected int getIP() { * Unique down to millisecond */ protected short getHiTime() { - return (short) ( System.currentTimeMillis() >>> 32 ); + return (short) ( currentTimeMillis() >>> 32 ); } protected int getLoTime() { - return (int) System.currentTimeMillis(); + return (int) currentTimeMillis(); } } diff --git a/hibernate-core/src/main/java/org/hibernate/id/CompositeNestedGeneratedValueGenerator.java b/hibernate-core/src/main/java/org/hibernate/id/CompositeNestedGeneratedValueGenerator.java index 6600d2da689b..b6e44cdd7878 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/CompositeNestedGeneratedValueGenerator.java +++ b/hibernate-core/src/main/java/org/hibernate/id/CompositeNestedGeneratedValueGenerator.java @@ -8,7 +8,6 @@ import java.util.ArrayList; import java.util.List; -import org.hibernate.HibernateException; import org.hibernate.Internal; import org.hibernate.boot.model.relational.Database; import org.hibernate.boot.model.relational.ExportableProducer; @@ -131,32 +130,9 @@ public void addGeneratedValuePlan(GenerationPlan plan) { } @Override - public Object generate(SharedSessionContractImplementor session, Object object) throws HibernateException { + public Object generate(SharedSessionContractImplementor session, Object object) { final Object context = generationContextLocator.locateGenerationContext( session, object ); - - final List generatedValues = compositeType.isMutable() ? - null : - new ArrayList<>( generationPlans.size() ); - for ( GenerationPlan generationPlan : generationPlans ) { - final BeforeExecutionGenerator generator = generationPlan.getGenerator(); - final Object generated; - if ( generator.generatedBeforeExecution( object, session ) ) { - final Object currentValue = generator.allowAssignedIdentifiers() - ? compositeType.getPropertyValue( context, generationPlan.getPropertyIndex(), session ) - : null; - generated = generator.generate( session, object, currentValue, INSERT ); - } - else { - throw new IdentifierGenerationException( "Identity generation isn't supported for composite ids" ); - } - if ( generatedValues != null ) { - generatedValues.add( generated ); - } - else { - generationPlan.getInjector().set( context, generated ); - } - } - + final List generatedValues = generatedValues( session, object, context ); if ( generatedValues != null) { final Object[] values = compositeType.getPropertyValues( context ); for ( int i = 0; i < generatedValues.size(); i++ ) { @@ -169,16 +145,41 @@ public Object generate(SharedSessionContractImplementor session, Object object) } } + private List generatedValues(SharedSessionContractImplementor session, Object object, Object context) { + final List generatedValues = + compositeType.isMutable() + ? null + : new ArrayList<>( generationPlans.size() ); + for ( var generationPlan : generationPlans ) { + final var generator = generationPlan.getGenerator(); + if ( !generator.generatedBeforeExecution( object, session ) ) { + throw new IdentifierGenerationException( "Identity generation isn't supported for composite ids" ); + } + final Object currentValue = + generator.allowAssignedIdentifiers() + ? compositeType.getPropertyValue( context, generationPlan.getPropertyIndex(), session ) + : null; + final Object generated = generator.generate( session, object, currentValue, INSERT ); + if ( generatedValues != null ) { + generatedValues.add( generated ); + } + else { + generationPlan.getInjector().set( context, generated ); + } + } + return generatedValues; + } + @Override public void registerExportables(Database database) { - for ( GenerationPlan plan : generationPlans ) { + for ( var plan : generationPlans ) { plan.registerExportables( database ); } } @Override public void initialize(SqlStringGenerationContext context) { - for ( GenerationPlan plan : generationPlans ) { + for ( var plan : generationPlans ) { plan.initialize( context ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/id/GUIDGenerator.java b/hibernate-core/src/main/java/org/hibernate/id/GUIDGenerator.java index 68ff6a79575a..4583a778fc21 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/GUIDGenerator.java +++ b/hibernate-core/src/main/java/org/hibernate/id/GUIDGenerator.java @@ -38,21 +38,22 @@ public Object generate(SharedSessionContractImplementor session, Object obj) thr final String sql = session.getJdbcServices().getJdbcEnvironment().getDialect().getSelectGUIDString(); try { final var jdbcCoordinator = session.getJdbcCoordinator(); - final var st = jdbcCoordinator.getStatementPreparer().prepareStatement( sql ); + final var statement = jdbcCoordinator.getStatementPreparer().prepareStatement( sql ); + final var resourceRegistry = jdbcCoordinator.getLogicalConnection().getResourceRegistry(); try { - final var rs = jdbcCoordinator.getResultSetReturn().extract( st, sql ); + final var resultSet = jdbcCoordinator.getResultSetReturn().extract( statement, sql ); try { - if ( !rs.next() ) { + if ( !resultSet.next() ) { throw new HibernateException( "The database returned no GUID identity value" ); } - return rs.getString( 1 ); + return resultSet.getString( 1 ); } finally { - jdbcCoordinator.getLogicalConnection().getResourceRegistry().release( rs, st ); + resourceRegistry.release( resultSet, statement ); } } finally { - jdbcCoordinator.getLogicalConnection().getResourceRegistry().release( st ); + resourceRegistry.release( statement ); jdbcCoordinator.afterStatementExecution(); } } 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 4873709e0006..d0c4d2faa9b1 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/IdentifierGeneratorHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/id/IdentifierGeneratorHelper.java @@ -27,7 +27,6 @@ import org.hibernate.persister.entity.EntityPersister; import org.hibernate.service.ServiceRegistry; import org.hibernate.type.EntityType; -import org.hibernate.type.Type; import static org.hibernate.cfg.MappingSettings.ID_DB_STRUCTURE_NAMING_STRATEGY; import static org.hibernate.engine.internal.ForeignKeys.getEntityIdentifierIfNotUnsaved; @@ -83,7 +82,7 @@ else if ( integralType == BigDecimal.class ) { public static Object getForeignId( String entityName, String propertyName, SharedSessionContractImplementor sessionImplementor, Object object) { - final EntityPersister entityDescriptor = + final var persister = sessionImplementor.getFactory().getMappingMetamodel() .getEntityDescriptor( entityName ); if ( sessionImplementor instanceof SessionImplementor statefulSession @@ -93,8 +92,8 @@ public static Object getForeignId( //throw new IdentifierGenerationException("save associated object first, or disable cascade for inverse association"); } else { - return identifier( sessionImplementor, entityType( propertyName, entityDescriptor ), - associatedEntity( entityName, propertyName, object, entityDescriptor ) ); + return identifier( sessionImplementor, entityType( propertyName, persister ), + associatedEntity( entityName, propertyName, object, persister ) ); } } @@ -109,19 +108,19 @@ private static Object associatedEntity( } private static Object identifier( - SharedSessionContractImplementor sessionImplementor, + SharedSessionContractImplementor session, EntityType foreignValueSourceType, Object associatedEntity) { final String associatedEntityName = foreignValueSourceType.getAssociatedEntityName(); try { - return getEntityIdentifierIfNotUnsaved( associatedEntityName, associatedEntity, sessionImplementor ); + return getEntityIdentifierIfNotUnsaved( associatedEntityName, associatedEntity, session ); } catch (TransientObjectException toe) { - if ( sessionImplementor instanceof Session statefulSession ) { + if ( session instanceof Session statefulSession ) { statefulSession.persist( associatedEntityName, associatedEntity ); - return sessionImplementor.getContextEntityIdentifier( associatedEntity ); + return session.getContextEntityIdentifier( associatedEntity ); } - else if ( sessionImplementor instanceof StatelessSession statelessSession ) { + else if ( session instanceof StatelessSession statelessSession ) { return statelessSession.insert( associatedEntityName, associatedEntity ); } else { @@ -131,10 +130,9 @@ else if ( sessionImplementor instanceof StatelessSession statelessSession ) { } private static EntityType entityType(String propertyName, EntityPersister entityDescriptor) { - final Type propertyType = entityDescriptor.getPropertyType( propertyName ); - if ( propertyType instanceof EntityType ) { + if ( entityDescriptor.getPropertyType( propertyName ) instanceof EntityType entityType ) { // the normal case - return (EntityType) propertyType; + return entityType; } else { // try identifier mapper @@ -246,7 +244,7 @@ public boolean gt(long value) { } public IntegralDataTypeHolder copy() { - BasicHolder copy = new BasicHolder( exactType ); + final var copy = new BasicHolder( exactType ); copy.value = value; return copy; } @@ -301,14 +299,16 @@ public String toString() { } @Override - public boolean equals(Object o) { - if ( this == o ) { + public boolean equals(Object object) { + if ( this == object ) { return true; } - if ( !(o instanceof BasicHolder that) ) { + else if ( !(object instanceof BasicHolder that) ) { return false; } - return value == that.value; + else { + return this.value == that.value; + } } @Override @@ -326,7 +326,7 @@ public IntegralDataTypeHolder initialize(long value) { } public IntegralDataTypeHolder initialize(ResultSet resultSet, long defaultValue) throws SQLException { - final BigDecimal rsValue = resultSet.getBigDecimal( 1 ); + final var rsValue = resultSet.getBigDecimal( 1 ); if ( resultSet.wasNull() ) { return initialize( defaultValue ); } @@ -411,7 +411,7 @@ public boolean gt(long value) { } public IntegralDataTypeHolder copy() { - BigIntegerHolder copy = new BigIntegerHolder(); + final var copy = new BigIntegerHolder(); copy.value = value; return copy; } @@ -457,14 +457,16 @@ public String toString() { } @Override - public boolean equals(Object o) { - if ( this == o ) { + public boolean equals(Object object) { + if ( this == object ) { return true; } - if ( !(o instanceof BigIntegerHolder that) ) { + else if ( !(object instanceof BigIntegerHolder that) ) { return false; } - return Objects.equals( value, that.value ); + else { + return Objects.equals( this.value, that.value ); + } } @Override @@ -482,7 +484,7 @@ public IntegralDataTypeHolder initialize(long value) { } public IntegralDataTypeHolder initialize(ResultSet resultSet, long defaultValue) throws SQLException { - final BigDecimal rsValue = resultSet.getBigDecimal( 1 ); + final var rsValue = resultSet.getBigDecimal( 1 ); if ( resultSet.wasNull() ) { return initialize( defaultValue ); } @@ -567,7 +569,7 @@ public boolean gt(long value) { } public IntegralDataTypeHolder copy() { - BigDecimalHolder copy = new BigDecimalHolder(); + final var copy = new BigDecimalHolder(); copy.value = value; return copy; } @@ -613,14 +615,16 @@ public String toString() { } @Override - public boolean equals(Object o) { - if ( this == o ) { + public boolean equals(Object object) { + if ( this == object ) { return true; } - if ( !(o instanceof BigDecimalHolder that) ) { + else if ( !(object instanceof BigDecimalHolder that) ) { return false; } - return Objects.equals( this.value, that.value ); + else { + return Objects.equals( this.value, that.value ); + } } @Override @@ -630,8 +634,6 @@ public int hashCode() { } public static ImplicitDatabaseObjectNamingStrategy getNamingStrategy(Properties params, ServiceRegistry serviceRegistry) { - final StrategySelector strategySelector = serviceRegistry.requireService( StrategySelector.class ); - final String namingStrategySetting = coalesceSuppliedValues( () -> { final String localSetting = getString( ID_DB_STRUCTURE_NAMING_STRATEGY, params ); @@ -641,8 +643,8 @@ public static ImplicitDatabaseObjectNamingStrategy getNamingStrategy(Properties return localSetting; }, () -> { - final ConfigurationService configurationService = serviceRegistry.requireService( ConfigurationService.class ); - final String globalSetting = getString( ID_DB_STRUCTURE_NAMING_STRATEGY, configurationService.getSettings() ); + final var settings = serviceRegistry.requireService( ConfigurationService.class ).getSettings(); + final String globalSetting = getString( ID_DB_STRUCTURE_NAMING_STRATEGY, settings ); if ( globalSetting != null ) { INCUBATION_LOGGER.incubatingSetting( ID_DB_STRUCTURE_NAMING_STRATEGY ); } @@ -650,8 +652,8 @@ public static ImplicitDatabaseObjectNamingStrategy getNamingStrategy(Properties }, StandardNamingStrategy.class::getName ); - - return strategySelector.resolveStrategy( ImplicitDatabaseObjectNamingStrategy.class, namingStrategySetting ); + return serviceRegistry.requireService( StrategySelector.class ) + .resolveStrategy( ImplicitDatabaseObjectNamingStrategy.class, namingStrategySetting ); } /** diff --git a/hibernate-core/src/main/java/org/hibernate/id/IdentityGenerator.java b/hibernate-core/src/main/java/org/hibernate/id/IdentityGenerator.java index ecd911189ee7..1257aef2f832 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/IdentityGenerator.java +++ b/hibernate-core/src/main/java/org/hibernate/id/IdentityGenerator.java @@ -4,9 +4,6 @@ */ package org.hibernate.id; -import java.util.List; - -import org.hibernate.boot.spi.SessionFactoryOptions; import org.hibernate.dialect.Dialect; import org.hibernate.generator.OnExecutionGenerator; import org.hibernate.id.insert.BasicSelectingDelegate; @@ -14,7 +11,6 @@ import org.hibernate.id.insert.InsertGeneratedIdentifierDelegate; import org.hibernate.id.insert.InsertReturningDelegate; import org.hibernate.id.insert.UniqueKeySelectingDelegate; -import org.hibernate.metamodel.mapping.ModelPart; import org.hibernate.persister.entity.EntityPersister; import static org.hibernate.generator.EventType.INSERT; @@ -54,9 +50,9 @@ public String[] getReferencedColumnValues(Dialect dialect) { @Override public InsertGeneratedIdentifierDelegate getGeneratedIdentifierDelegate(EntityPersister persister) { - final Dialect dialect = persister.getFactory().getJdbcServices().getDialect(); - final SessionFactoryOptions sessionFactoryOptions = persister.getFactory().getSessionFactoryOptions(); - final List generatedProperties = persister.getGeneratedProperties( INSERT ); + final var dialect = persister.getFactory().getJdbcServices().getDialect(); + final var sessionFactoryOptions = persister.getFactory().getSessionFactoryOptions(); + final var generatedProperties = persister.getGeneratedProperties( INSERT ); if ( generatedProperties.size() == 1 && sessionFactoryOptions.isGetGeneratedKeysEnabled() ) { // Use Connection#prepareStatement(sql, Statement.RETURN_GENERATED_KEYS) when only retrieving identity assert generatedProperties.get( 0 ).isEntityIdentifierMapping(); 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 abd3e7508e67..2e7611076870 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/IncrementGenerator.java +++ b/hibernate-core/src/main/java/org/hibernate/id/IncrementGenerator.java @@ -4,8 +4,6 @@ */ package org.hibernate.id; -import java.sql.PreparedStatement; -import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; @@ -16,9 +14,6 @@ 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; -import org.hibernate.engine.jdbc.env.spi.IdentifierHelper; -import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.generator.GeneratorCreationContext; @@ -83,8 +78,9 @@ public synchronized Object generate(SharedSessionContractImplementor session, Ob public void configure(GeneratorCreationContext creationContext, Properties parameters) throws MappingException { returnClass = creationContext.getType().getReturnedClass(); - final JdbcEnvironment jdbcEnvironment = creationContext.getDatabase().getJdbcEnvironment(); - final IdentifierHelper identifierHelper = jdbcEnvironment.getIdentifierHelper(); + final var jdbcEnvironment = creationContext.getDatabase().getJdbcEnvironment(); + final var identifierHelper = jdbcEnvironment.getIdentifierHelper(); + column = identifierHelper.normalizeQuoting( identifierHelper.toIdentifier( getString( COLUMN, PK, parameters ) ) ) .render( jdbcEnvironment.getDialect() ); @@ -99,14 +95,14 @@ public void configure(GeneratorCreationContext creationContext, Properties param @Override public void initialize(SqlStringGenerationContext context) { - StringBuilder union = new StringBuilder(); + final var union = new StringBuilder(); for ( int i = 0; i < physicalTableNames.size(); i++ ) { final String tableName = context.format( physicalTableNames.get( i ) ); if ( physicalTableNames.size() > 1 ) { union.append( "select max(" ).append( column ).append( ") as mx from " ); } union.append( tableName ); - final Dialect dialect = context.getDialect(); + final var dialect = context.getDialect(); if ( i < physicalTableNames.size() - 1 ) { union.append( " union " ); if ( dialect.supportsUnionAll() ) { @@ -133,12 +129,14 @@ private void initializePreviousValueHolder(SharedSessionContractImplementor sess CORE_LOGGER.tracef( "Fetching initial value: %s", sql ); } try { - final PreparedStatement st = session.getJdbcCoordinator().getStatementPreparer().prepareStatement( sql ); + final var jdbcCoordinator = session.getJdbcCoordinator(); + final var statement = jdbcCoordinator.getStatementPreparer().prepareStatement( sql ); + final var resourceRegistry = jdbcCoordinator.getLogicalConnection().getResourceRegistry(); try { - final ResultSet rs = session.getJdbcCoordinator().getResultSetReturn().extract( st, sql ); + final var resultSet = jdbcCoordinator.getResultSetReturn().extract( statement, sql ); try { - if ( rs.next() ) { - previousValueHolder.initialize( rs, 0L ).increment(); + if ( resultSet.next() ) { + previousValueHolder.initialize( resultSet, 0L ).increment(); } else { previousValueHolder.initialize( 1L ); @@ -149,12 +147,12 @@ private void initializePreviousValueHolder(SharedSessionContractImplementor sess } } finally { - session.getJdbcCoordinator().getLogicalConnection().getResourceRegistry().release( rs, st ); + resourceRegistry.release( resultSet, statement ); } } finally { - session.getJdbcCoordinator().getLogicalConnection().getResourceRegistry().release( st ); - session.getJdbcCoordinator().afterStatementExecution(); + resourceRegistry.release( statement ); + jdbcCoordinator.afterStatementExecution(); } } catch (SQLException sqle) { diff --git a/hibernate-core/src/main/java/org/hibernate/id/NativeGenerator.java b/hibernate-core/src/main/java/org/hibernate/id/NativeGenerator.java index c9b3a4d0bdaa..56b51b9c1bad 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/NativeGenerator.java +++ b/hibernate-core/src/main/java/org/hibernate/id/NativeGenerator.java @@ -26,7 +26,6 @@ import java.lang.reflect.Member; import java.util.EnumSet; -import java.util.Map; import java.util.Properties; import static org.hibernate.boot.model.internal.GeneratorParameters.collectParameters; @@ -68,10 +67,9 @@ public void initialize( Member member, GeneratorCreationContext context) { this.annotation = annotation; - - generationType = context.getDatabase() - .getDialect() - .getNativeValueGenerationStrategy(); + generationType = + context.getDatabase().getDialect() + .getNativeValueGenerationStrategy(); switch ( generationType ) { case TABLE: { dialectNativeGenerator = new TableGenerator(); @@ -148,34 +146,31 @@ private void applyProperties( Properties properties, SequenceGenerator sequenceAnnotation, GeneratorCreationContext creationContext) { - //noinspection unchecked,rawtypes - final Map mapRef = (Map) properties; - mapRef.put( GENERATOR_NAME, sequenceAnnotation.name() ); - applyCommonConfiguration( mapRef, creationContext ); - SequenceStyleGenerator.applyConfiguration( sequenceAnnotation, mapRef::put ); + properties.put( GENERATOR_NAME, sequenceAnnotation.name() ); + applyCommonConfiguration( properties, creationContext ); + SequenceStyleGenerator.applyConfiguration( sequenceAnnotation, properties::put ); } private void applyProperties( Properties properties, jakarta.persistence.TableGenerator tableGenerator, GeneratorCreationContext creationContext) { - //noinspection unchecked,rawtypes - final Map mapRef = (Map) properties; - mapRef.put( GENERATOR_NAME, tableGenerator.name() ); - applyCommonConfiguration( mapRef, creationContext ); - TableGenerator.applyConfiguration( tableGenerator, mapRef::put ); + properties.put( GENERATOR_NAME, tableGenerator.name() ); + applyCommonConfiguration( properties, creationContext ); + TableGenerator.applyConfiguration( tableGenerator, properties::put ); } private static void applyCommonConfiguration( - Map mapRef, + Properties properties, GeneratorCreationContext context) { collectParameters( context.getProperty().getValue(), context.getDatabase().getDialect(), context.getRootClass(), - mapRef::put, - context.getServiceRegistry().requireService( ConfigurationService.class ) + properties::put, + context.getServiceRegistry() + .requireService( ConfigurationService.class ) ); - mapRef.put( INCREMENT_PARAM, 1 ); + properties.put( INCREMENT_PARAM, 1 ); } } From 76b35f0e295355382f2cb713b8c09ef73dcdbde0 Mon Sep 17 00:00:00 2001 From: Gavin King Date: Sat, 27 Sep 2025 18:47:39 +0200 Subject: [PATCH 2/6] allow passing a class to 'hibernate.id.optimizer.pooled.preferred' and clean GeneratorParameters a bit --- .../model/internal/GeneratorParameters.java | 113 +++++++++--------- 1 file changed, 54 insertions(+), 59 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/GeneratorParameters.java b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/GeneratorParameters.java index d7d54d1e3d7a..ed6d73a50f53 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/GeneratorParameters.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/GeneratorParameters.java @@ -19,13 +19,11 @@ import org.hibernate.generator.GeneratorCreationContext; import org.hibernate.id.Configurable; 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.mapping.Column; import org.hibernate.mapping.RootClass; -import org.hibernate.mapping.Table; import jakarta.persistence.SequenceGenerator; import jakarta.persistence.TableGenerator; @@ -40,10 +38,19 @@ import static org.hibernate.id.OptimizableGenerator.IMPLICIT_NAME_BASE; import static org.hibernate.id.OptimizableGenerator.INCREMENT_PARAM; import static org.hibernate.id.OptimizableGenerator.INITIAL_PARAM; +import static org.hibernate.id.PersistentIdentifierGenerator.CATALOG; +import static org.hibernate.id.PersistentIdentifierGenerator.OPTIONS; import static org.hibernate.id.PersistentIdentifierGenerator.PK; +import static org.hibernate.id.PersistentIdentifierGenerator.SCHEMA; import static org.hibernate.id.PersistentIdentifierGenerator.TABLE; import static org.hibernate.id.PersistentIdentifierGenerator.TABLES; import static org.hibernate.boot.BootLogging.BOOT_LOGGER; +import static org.hibernate.id.enhanced.SequenceStyleGenerator.SEQUENCE_PARAM; +import static org.hibernate.id.enhanced.TableGenerator.CONFIG_PREFER_SEGMENT_PER_ENTITY; +import static org.hibernate.id.enhanced.TableGenerator.SEGMENT_COLUMN_PARAM; +import static org.hibernate.id.enhanced.TableGenerator.SEGMENT_VALUE_PARAM; +import static org.hibernate.id.enhanced.TableGenerator.TABLE_PARAM; +import static org.hibernate.id.enhanced.TableGenerator.VALUE_COLUMN_PARAM; import static org.hibernate.internal.util.StringHelper.isNotBlank; import static org.hibernate.internal.util.collections.CollectionHelper.isNotEmpty; @@ -111,16 +118,14 @@ static void collectBaselineProperties( BiConsumer parameterCollector, ConfigurationService configService) { //init the table here instead of earlier, so that we can get a quoted table name - //TODO: would it be better to simply pass the qualified table name, instead of - // splitting it up into schema/catalog/table names - final String tableName = identifierValue.getTable().getQuotedName( dialect ); - parameterCollector.accept( TABLE, tableName ); + //TODO: would it be better to simply pass the qualified table name, + // instead of splitting it up into schema/catalog/table names + parameterCollector.accept( TABLE, identifierValue.getTable().getQuotedName( dialect ) ); //pass the column name (a generated id almost always has a single column) if ( identifierValue.getColumnSpan() == 1 ) { - final Column column = (Column) identifierValue.getSelectables().get( 0 ); - final String columnName = column.getQuotedName( dialect ); - parameterCollector.accept( PK, columnName ); + final var column = (Column) identifierValue.getSelectables().get( 0 ); + parameterCollector.accept( PK, column.getQuotedName( dialect ) ); } //pass the entity-name, if not a collection-id @@ -139,25 +144,35 @@ static void collectBaselineProperties( parameterCollector.accept( TABLES, identityTablesString( dialect, rootClass ) ); } else { - parameterCollector.accept( TABLES, tableName ); - parameterCollector.accept( IMPLICIT_NAME_BASE, tableName ); + parameterCollector.accept( TABLES, identifierValue.getTable().getQuotedName( dialect ) ); + parameterCollector.accept( IMPLICIT_NAME_BASE, identifierValue.getTable().getQuotedName( dialect ) ); } parameterCollector.accept( CONTRIBUTOR_NAME, identifierValue.getBuildingContext().getCurrentContributorName() ); - final Map settings = configService.getSettings(); + final var settings = configService.getSettings(); if ( settings.containsKey( PREFERRED_POOLED_OPTIMIZER ) ) { - parameterCollector.accept( - PREFERRED_POOLED_OPTIMIZER, - (String) settings.get( PREFERRED_POOLED_OPTIMIZER ) - ); + parameterCollector.accept( PREFERRED_POOLED_OPTIMIZER, + optimizerClassName( settings.get( PREFERRED_POOLED_OPTIMIZER ) ) ); + } + } + + private static String optimizerClassName(Object optimizerSetting) { + if ( optimizerSetting instanceof String string ) { + return string; + } + else if ( optimizerSetting instanceof Class clazz ) { + return clazz.getName(); + } + else { + return optimizerSetting.toString(); } } public static String identityTablesString(Dialect dialect, RootClass rootClass) { final var tables = new StringBuilder(); - for ( Table table : rootClass.getIdentityTables() ) { + for ( var table : rootClass.getIdentityTables() ) { tables.append( table.getQuotedName( dialect ) ); if ( !tables.isEmpty() ) { tables.append( ", " ); @@ -188,67 +203,51 @@ public static void interpretTableGenerator( 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" ); + definitionBuilder.addParam( CONFIG_PREFER_SEGMENT_PER_ENTITY, "true" ); final String catalog = tableGeneratorAnnotation.catalog(); if ( isNotBlank( catalog ) ) { - definitionBuilder.addParam( PersistentIdentifierGenerator.CATALOG, catalog ); + definitionBuilder.addParam( CATALOG, catalog ); } final String schema = tableGeneratorAnnotation.schema(); if ( isNotBlank( schema ) ) { - definitionBuilder.addParam( PersistentIdentifierGenerator.SCHEMA, schema ); + definitionBuilder.addParam( SCHEMA, schema ); } final String table = tableGeneratorAnnotation.table(); if ( isNotBlank( table ) ) { - definitionBuilder.addParam( org.hibernate.id.enhanced.TableGenerator.TABLE_PARAM, table ); + definitionBuilder.addParam( TABLE_PARAM, table ); } final String pkColumnName = tableGeneratorAnnotation.pkColumnName(); if ( isNotBlank( pkColumnName ) ) { - definitionBuilder.addParam( - org.hibernate.id.enhanced.TableGenerator.SEGMENT_COLUMN_PARAM, - pkColumnName - ); + definitionBuilder.addParam( SEGMENT_COLUMN_PARAM, pkColumnName ); } final String pkColumnValue = tableGeneratorAnnotation.pkColumnValue(); if ( isNotBlank( pkColumnValue ) ) { - definitionBuilder.addParam( - org.hibernate.id.enhanced.TableGenerator.SEGMENT_VALUE_PARAM, - pkColumnValue - ); + definitionBuilder.addParam( SEGMENT_VALUE_PARAM, pkColumnValue ); } final String valueColumnName = tableGeneratorAnnotation.valueColumnName(); if ( isNotBlank( valueColumnName ) ) { - definitionBuilder.addParam( - org.hibernate.id.enhanced.TableGenerator.VALUE_COLUMN_PARAM, - valueColumnName - ); + definitionBuilder.addParam( VALUE_COLUMN_PARAM, valueColumnName ); } final String options = tableGeneratorAnnotation.options(); if ( isNotBlank( options ) ) { - definitionBuilder.addParam( - PersistentIdentifierGenerator.OPTIONS, - options - ); + definitionBuilder.addParam( OPTIONS, options ); } - definitionBuilder.addParam( - INCREMENT_PARAM, - String.valueOf( tableGeneratorAnnotation.allocationSize() ) - ); + definitionBuilder.addParam( INCREMENT_PARAM, + String.valueOf( tableGeneratorAnnotation.allocationSize() ) ); - // See comment on HHH-4884 wrt initialValue. Basically initialValue is really the stated value + 1 - definitionBuilder.addParam( - INITIAL_PARAM, - String.valueOf( tableGeneratorAnnotation.initialValue() + 1 ) - ); + // See comment on HHH-4884 wrt initialValue. Basically initialValue is really the stated value + 1 + definitionBuilder.addParam( INITIAL_PARAM, + String.valueOf( tableGeneratorAnnotation.initialValue() + 1 ) ); - // TODO : implement unique-constraint support + // TODO: implement unique constraint support if ( isNotEmpty( tableGeneratorAnnotation.uniqueConstraints() ) ) { BOOT_LOGGER.ignoringTableGeneratorConstraints( tableGeneratorAnnotation.name() ); } @@ -263,31 +262,27 @@ public static void interpretSequenceGenerator( final String catalog = sequenceGeneratorAnnotation.catalog(); if ( isNotBlank( catalog ) ) { - definitionBuilder.addParam( PersistentIdentifierGenerator.CATALOG, catalog ); + definitionBuilder.addParam( CATALOG, catalog ); } final String schema = sequenceGeneratorAnnotation.schema(); if ( isNotBlank( schema ) ) { - definitionBuilder.addParam( PersistentIdentifierGenerator.SCHEMA, schema ); + definitionBuilder.addParam( SCHEMA, schema ); } final String sequenceName = sequenceGeneratorAnnotation.sequenceName(); if ( isNotBlank( sequenceName ) ) { - definitionBuilder.addParam( SequenceStyleGenerator.SEQUENCE_PARAM, sequenceName ); + definitionBuilder.addParam( SEQUENCE_PARAM, sequenceName ); } - definitionBuilder.addParam( - INCREMENT_PARAM, - String.valueOf( sequenceGeneratorAnnotation.allocationSize() ) - ); - definitionBuilder.addParam( - INITIAL_PARAM, - String.valueOf( sequenceGeneratorAnnotation.initialValue() ) - ); + definitionBuilder.addParam( INCREMENT_PARAM, + String.valueOf( sequenceGeneratorAnnotation.allocationSize() ) ); + definitionBuilder.addParam( INITIAL_PARAM, + String.valueOf( sequenceGeneratorAnnotation.initialValue() ) ); final String options = sequenceGeneratorAnnotation.options(); if ( isNotBlank( options ) ) { - definitionBuilder.addParam( PersistentIdentifierGenerator.OPTIONS, options ); + definitionBuilder.addParam( OPTIONS, options ); } } } From 5c57ed8c0c2822d4d6b79b2b1c10f76da801ee58 Mon Sep 17 00:00:00 2001 From: Gavin King Date: Sat, 27 Sep 2025 18:47:56 +0200 Subject: [PATCH 3/6] improve javadoc of "pooled" optimizers --- .../org/hibernate/cfg/MappingSettings.java | 16 ++++++++--- .../org/hibernate/id/enhanced/Optimizer.java | 5 ++++ .../id/enhanced/PooledLoOptimizer.java | 19 +++++++++++-- .../id/enhanced/PooledOptimizer.java | 27 ++++++++++++++----- 4 files changed, 55 insertions(+), 12 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/MappingSettings.java b/hibernate-core/src/main/java/org/hibernate/cfg/MappingSettings.java index 429e310dd036..6de4e0447f70 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/MappingSettings.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/MappingSettings.java @@ -118,12 +118,20 @@ public interface MappingSettings { String KEYWORD_AUTO_QUOTING_ENABLED = "hibernate.auto_quote_keyword"; /** - * When a generator specifies an increment size and an optimizer was not explicitly - * specified, which of the "pooled" optimizers should be preferred? Can specify an - * optimizer short name or the name of a class which implements - * {@link org.hibernate.id.enhanced.Optimizer}. + * Specifies an {@linkplain org.hibernate.id.enhanced.Optimizer optimizer} + * which should be used when a generator specifies an {@code allocationSize} + * and no optimizer is not explicitly specified, either: + *
    + *
  • a class implementing {@link org.hibernate.id.enhanced.Optimizer}, + *
  • the name of a class implementing {@code Optimizer}, or
  • + *
  • an {@linkplain StandardOptimizerDescriptor optimizer short name}. + *
* * @settingDefault {@link StandardOptimizerDescriptor#POOLED} + * + * @see org.hibernate.id.enhanced.PooledOptimizer + * @see org.hibernate.id.enhanced.PooledLoOptimizer + * @see org.hibernate.id.enhanced.HiLoOptimizer */ String PREFERRED_POOLED_OPTIMIZER = "hibernate.id.optimizer.pooled.preferred"; diff --git a/hibernate-core/src/main/java/org/hibernate/id/enhanced/Optimizer.java b/hibernate-core/src/main/java/org/hibernate/id/enhanced/Optimizer.java index ba28fc7fc31c..0ee729b50d4a 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/enhanced/Optimizer.java +++ b/hibernate-core/src/main/java/org/hibernate/id/enhanced/Optimizer.java @@ -15,6 +15,9 @@ * this optimization takes the form of trying to ensure we do not have to * hit the database on each and every request to get an identifier value. *

+ * An optimizer may be selected by setting the configuration property + * {@value org.hibernate.cfg.MappingSettings#PREFERRED_POOLED_OPTIMIZER}. + *

* Optimizers work on constructor injection. They should provide a * constructor accepting the following arguments: *

    @@ -22,6 +25,8 @@ *
  1. {@code int} - The increment size
  2. *
* + * @see org.hibernate.cfg.MappingSettings#PREFERRED_POOLED_OPTIMIZER + * * @author Steve Ebersole */ public interface Optimizer { diff --git a/hibernate-core/src/main/java/org/hibernate/id/enhanced/PooledLoOptimizer.java b/hibernate-core/src/main/java/org/hibernate/id/enhanced/PooledLoOptimizer.java index 9504a5a04686..32934673786d 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/enhanced/PooledLoOptimizer.java +++ b/hibernate-core/src/main/java/org/hibernate/id/enhanced/PooledLoOptimizer.java @@ -17,12 +17,27 @@ import java.util.concurrent.locks.ReentrantLock; /** - * Variation of {@link PooledOptimizer} which interprets the incoming database - * value as the lo value, rather than the hi value. + * Optimizer which uses a pool of values, backed by a logical sequence. + * A logical sequence is usually just an unpooled sequence or table generator. + *

+ * The pool size is controlled by the {@code allocationSize} of a + * {@linkplain jakarta.persistence.SequenceGenerator sequence generator} or + * {@linkplain jakarta.persistence.TableGenerator sequence generator}. + *

+ * From time to time, the optimizer allocates a range of values to itself, + * interpreting the next value retrieved from the logical sequence as the + * lower bound on the range of newly allocated ids. Thus, the generated ids + * begin with the value retrieved from the logical sequence. + *

+ * The {@link PooledOptimizer} is similar, but interprets the current value + * of the logical sequence as an upper bound on the range of already-allocated + * ids. * * @author Steve Ebersole * * @see PooledOptimizer + * @see jakarta.persistence.SequenceGenerator#allocationSize + * @see jakarta.persistence.TableGenerator#allocationSize */ public class PooledLoOptimizer extends AbstractOptimizer { diff --git a/hibernate-core/src/main/java/org/hibernate/id/enhanced/PooledOptimizer.java b/hibernate-core/src/main/java/org/hibernate/id/enhanced/PooledOptimizer.java index 5aa17e674e82..71ac51df8686 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/enhanced/PooledOptimizer.java +++ b/hibernate-core/src/main/java/org/hibernate/id/enhanced/PooledOptimizer.java @@ -20,18 +20,33 @@ import java.util.concurrent.locks.ReentrantLock; /** - * Optimizer which uses a pool of values, storing the next low value of the range - * in the database. + * Optimizer which uses a pool of values, backed by a logical sequence. + * A logical sequence is usually just an unpooled sequence or table generator. *

- * This optimizer works essentially the same as the {@link HiLoOptimizer}, except - * that here the bucket ranges are actually encoded into the database structures. + * The pool size is controlled by the {@code allocationSize} of a + * {@linkplain jakarta.persistence.SequenceGenerator sequence generator} or + * {@linkplain jakarta.persistence.TableGenerator sequence generator}. *

- * If you prefer that the database value be interpreted as the bottom end of our - * current range, then use the {@link PooledLoOptimizer} strategy. + * This optimizer interprets the current value held by its underlying logical + * sequence (that is, the last value generated by a database sequence, or the + * current value of a table row emulating a sequence) as an upper bound on the + * range of already-allocated ids. From time to time, the optimizer allocates + * a range of values to itself, interpreting the next value retrieved from the + * logical sequence as an upper bound on the range of newly allocated ids. + *

+ * The {@link PooledLoOptimizer} is similar, but interprets the current value + * of the logical sequence as a lower bound on the range of already-allocated + * ids. + *

+ * This optimizer has similar performance characteristics to the + * {@link HiLoOptimizer}, but here the range bounds are stored directly by the + * underlying database structures. * * @author Steve Ebersole * * @see PooledLoOptimizer + * @see jakarta.persistence.SequenceGenerator#allocationSize + * @see jakarta.persistence.TableGenerator#allocationSize */ public class PooledOptimizer extends AbstractOptimizer implements InitialValueAwareOptimizer { From e6f6831b7be2defbe18230ea7cd84989d06f28fe Mon Sep 17 00:00:00 2001 From: Gavin King Date: Sat, 27 Sep 2025 19:49:36 +0200 Subject: [PATCH 4/6] modernize StandardOptimizerDescriptor and make fromExternalName() case-insensitive --- .../enhanced/StandardOptimizerDescriptor.java | 67 ++++++------------- 1 file changed, 22 insertions(+), 45 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/id/enhanced/StandardOptimizerDescriptor.java b/hibernate-core/src/main/java/org/hibernate/id/enhanced/StandardOptimizerDescriptor.java index 6df02abd2704..2b94d0b0dc37 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/enhanced/StandardOptimizerDescriptor.java +++ b/hibernate-core/src/main/java/org/hibernate/id/enhanced/StandardOptimizerDescriptor.java @@ -4,8 +4,6 @@ */ package org.hibernate.id.enhanced; -import org.hibernate.AssertionFailure; - import static org.hibernate.internal.util.StringHelper.isEmpty; /** @@ -46,55 +44,34 @@ public enum StandardOptimizerDescriptor implements OptimizerDescriptor { @Override public String getExternalName() { - switch ( this ) { - case NONE: - return "none"; - case HILO: - return "hilo"; - case LEGACY_HILO: - return "legacy-hilo"; - case POOLED: - return "pooled"; - case POOLED_LO: - return "pooled-lo"; - case POOLED_LOTL: - return "pooled-lotl"; - } - throw new AssertionFailure( "unknown StandardOptimizerDescriptor" ); + return switch ( this ) { + case NONE -> "none"; + case HILO -> "hilo"; + case LEGACY_HILO -> "legacy-hilo"; + case POOLED -> "pooled"; + case POOLED_LO -> "pooled-lo"; + case POOLED_LOTL -> "pooled-lotl"; + }; } @Override public Class getOptimizerClass() { - switch ( this ) { - case NONE: - return NoopOptimizer.class; - case HILO: - return HiLoOptimizer.class; - case LEGACY_HILO: - return LegacyHiLoAlgorithmOptimizer.class; - case POOLED: - return PooledOptimizer.class; - case POOLED_LO: - return PooledLoOptimizer.class; - case POOLED_LOTL: - return PooledLoThreadLocalOptimizer.class; - } - throw new AssertionFailure( "unknown StandardOptimizerDescriptor" ); + return switch ( this ) { + case NONE -> NoopOptimizer.class; + case HILO -> HiLoOptimizer.class; + case LEGACY_HILO -> LegacyHiLoAlgorithmOptimizer.class; + case POOLED -> PooledOptimizer.class; + case POOLED_LO -> PooledLoOptimizer.class; + case POOLED_LOTL -> PooledLoThreadLocalOptimizer.class; + }; } @Override public boolean isPooled() { - switch ( this ) { - case NONE: - case HILO: - case LEGACY_HILO: - return false; - case POOLED: - case POOLED_LO: - case POOLED_LOTL: - return true; - } - throw new AssertionFailure( "unknown StandardOptimizerDescriptor" ); + return switch ( this ) { + case NONE, HILO, LEGACY_HILO -> false; + case POOLED, POOLED_LO, POOLED_LOTL -> true; + }; } /** @@ -111,8 +88,8 @@ public static OptimizerDescriptor fromExternalName(String externalName) { return NONE; } else { - for ( StandardOptimizerDescriptor value: values() ) { - if ( value.getExternalName().equals( externalName ) ) { + for ( var value: values() ) { + if ( value.getExternalName().equalsIgnoreCase( externalName ) ) { return value; } } From 218ea634e77b6087c491ee79e1fc62b0d16dec4a Mon Sep 17 00:00:00 2001 From: Gavin King Date: Sat, 27 Sep 2025 20:15:20 +0200 Subject: [PATCH 5/6] refactor TableGenerator.generate() --- .../id/enhanced/SequenceStyleGenerator.java | 3 +- .../hibernate/id/enhanced/TableGenerator.java | 69 ++++++++++--------- 2 files changed, 38 insertions(+), 34 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/id/enhanced/SequenceStyleGenerator.java b/hibernate-core/src/main/java/org/hibernate/id/enhanced/SequenceStyleGenerator.java index 5a106fbfaef5..d44d65157729 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/enhanced/SequenceStyleGenerator.java +++ b/hibernate-core/src/main/java/org/hibernate/id/enhanced/SequenceStyleGenerator.java @@ -7,7 +7,6 @@ import java.util.Properties; import java.util.function.BiConsumer; -import org.hibernate.HibernateException; import org.hibernate.MappingException; import org.hibernate.boot.model.naming.Identifier; import org.hibernate.boot.model.relational.Database; @@ -555,7 +554,7 @@ private String determineContributor(Properties params) { // IdentifierGenerator implementation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @Override - public Object generate(SharedSessionContractImplementor session, Object object) throws HibernateException { + public Object generate(SharedSessionContractImplementor session, Object object) { return optimizer.generate( databaseStructure.buildCallback( session ) ); } diff --git a/hibernate-core/src/main/java/org/hibernate/id/enhanced/TableGenerator.java b/hibernate-core/src/main/java/org/hibernate/id/enhanced/TableGenerator.java index 1d6e1ec3c08a..e22f4f0ee6e4 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/enhanced/TableGenerator.java +++ b/hibernate-core/src/main/java/org/hibernate/id/enhanced/TableGenerator.java @@ -520,39 +520,41 @@ private IntegralDataTypeHolder makeValue() { } @Override - public Object generate(final SharedSessionContractImplementor session, final Object obj) { - final var statementLogger = - session.getFactory().getJdbcServices() - .getSqlStatementLogger(); - final var statsCollector = session.getEventListenerManager(); - return optimizer.generate( - new AccessCallback() { - @Override - public IntegralDataTypeHolder getNextValue() { - return session.getTransactionCoordinator().createIsolationDelegate().delegateWork( - new AbstractReturningWork<>() { - @Override - public IntegralDataTypeHolder execute(Connection connection) throws SQLException { - return nextValue( connection, statementLogger, statsCollector, session ); - } - }, - true - ); - } - @Override - public String getTenantIdentifier() { - return session.getTenantIdentifier(); - } - } - ); + public Object generate(final SharedSessionContractImplementor session, final Object object) { + return optimizer.generate( new NextValueCallback( session ) ); + } + + private class NextValueCallback + extends AbstractReturningWork + implements AccessCallback { + private final SharedSessionContractImplementor session; + private NextValueCallback(SharedSessionContractImplementor session) { + this.session = session; + } + @Override + public IntegralDataTypeHolder getNextValue() { + return session.getTransactionCoordinator().createIsolationDelegate() + .delegateWork( this, true ); + } + @Override + public IntegralDataTypeHolder execute(Connection connection) + throws SQLException { + return nextValue( connection, session ); + } + @Override + public String getTenantIdentifier() { + return session.getTenantIdentifier(); + } } private IntegralDataTypeHolder nextValue( Connection connection, - SqlStatementLogger logger, - SessionEventListenerManager listener, SharedSessionContractImplementor session) - throws SQLException { + throws SQLException { + final var logger = + session.getFactory().getJdbcServices() + .getSqlStatementLogger(); + final var listener = session.getEventListenerManager(); final var value = makeValue(); int rows; do { @@ -636,7 +638,8 @@ private PreparedStatement prepareStatement( String sql, SqlStatementLogger logger, SessionEventListenerManager listener, - SharedSessionContractImplementor session) throws SQLException { + SharedSessionContractImplementor session) + throws SQLException { logger.logStatement( sql, FormatStyle.BASIC.getFormatter() ); final var eventMonitor = session.getEventMonitor(); final var creationEvent = eventMonitor.beginJdbcPreparedStatementCreationEvent(); @@ -661,7 +664,8 @@ private int executeUpdate( PreparedStatement ps, SessionEventListenerManager listener, String sql, - SharedSessionContractImplementor session) throws SQLException { + SharedSessionContractImplementor session) + throws SQLException { final var eventMonitor = session.getEventMonitor(); final var executionEvent = eventMonitor.beginJdbcPreparedStatementExecutionEvent(); try { @@ -678,7 +682,8 @@ private ResultSet executeQuery( PreparedStatement ps, SessionEventListenerManager listener, String sql, - SharedSessionContractImplementor session) throws SQLException { + SharedSessionContractImplementor session) + throws SQLException { final var eventMonitor = session.getEventMonitor(); final var executionEvent = eventMonitor.beginJdbcPreparedStatementExecutionEvent(); try { @@ -784,7 +789,7 @@ public void initialize(SqlStringGenerationContext context) { public static void applyConfiguration( jakarta.persistence.TableGenerator generatorConfig, BiConsumer configurationCollector) { - configurationCollector.accept( CONFIG_PREFER_SEGMENT_PER_ENTITY, "true" ); + configurationCollector.accept( CONFIG_PREFER_SEGMENT_PER_ENTITY, String.valueOf(true) ); applyIfNotEmpty( TABLE_PARAM, generatorConfig.table(), configurationCollector ); applyIfNotEmpty( CATALOG, generatorConfig.catalog(), configurationCollector ); From 775008fcfd0e2ecdf576dd152087466260305cf7 Mon Sep 17 00:00:00 2001 From: Gavin King Date: Sat, 27 Sep 2025 20:17:20 +0200 Subject: [PATCH 6/6] document that Optimizers are specific to @SequenceGenerator and @TableGenerator --- .../src/main/java/org/hibernate/id/enhanced/Optimizer.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hibernate-core/src/main/java/org/hibernate/id/enhanced/Optimizer.java b/hibernate-core/src/main/java/org/hibernate/id/enhanced/Optimizer.java index 0ee729b50d4a..d80398863bfc 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/enhanced/Optimizer.java +++ b/hibernate-core/src/main/java/org/hibernate/id/enhanced/Optimizer.java @@ -15,6 +15,9 @@ * this optimization takes the form of trying to ensure we do not have to * hit the database on each and every request to get an identifier value. *

+ * Optimizers are used with + * {@linkplain jakarta.persistence.SequenceGenerator sequence generators} + * and {@linkplain jakarta.persistence.TableGenerator table generators}. * An optimizer may be selected by setting the configuration property * {@value org.hibernate.cfg.MappingSettings#PREFERRED_POOLED_OPTIMIZER}. *