make PostInsertIdentifierGenerator extend InDatabaseGenerator

This commit is contained in:
Gavin 2022-12-01 20:30:50 +01:00 committed by Gavin King
parent 4b2f8ff8ae
commit 6a630e3515
48 changed files with 413 additions and 404 deletions

View File

@ -102,7 +102,7 @@ import org.hibernate.metamodel.CollectionClassification;
import org.hibernate.metamodel.spi.EmbeddableInstantiator;
import org.hibernate.query.named.NamedObjectRepository;
import org.hibernate.query.sqm.function.SqmFunctionDescriptor;
import org.hibernate.tuple.InMemoryGenerator;
import org.hibernate.tuple.Generator;
import org.hibernate.type.descriptor.java.JavaType;
import org.hibernate.type.descriptor.jdbc.JdbcType;
import org.hibernate.type.spi.TypeConfiguration;
@ -2315,7 +2315,7 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector
// It was done this way in the old code too, so no "regression" here; but
// it could be done better
try {
final InMemoryGenerator generator = identifierValueBinding.createGenerator(
final Generator generator = identifierValueBinding.createGenerator(
bootstrapContext.getIdentifierGeneratorFactory(),
dialect,
entityBinding

View File

@ -111,6 +111,15 @@ public interface IdentityColumnSupport {
*/
String getIdentityInsertString();
/**
* Is there a keyword used to insert a generated value into an identity column.
*
* @return {@code true} if the dialect does not support inserts that specify no column values.
*/
default boolean hasIdentityInsertKeyword() {
return getIdentityInsertString() != null;
}
/**
* The Delegate for dealing with IDENTITY columns using JDBC3 getGeneratedKeys
*

View File

@ -41,6 +41,7 @@ import org.hibernate.metamodel.mapping.PluralAttributeMapping;
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.SingleTableEntityPersister;
import org.hibernate.tuple.Generator;
import org.hibernate.tuple.InMemoryGenerator;
import org.hibernate.type.BasicType;
import org.hibernate.type.StandardBasicTypes;
@ -253,8 +254,8 @@ public class TemporaryTable implements Exportable, Contributable {
final PersistentClass entityBinding = runtimeModelCreationContext.getBootModel()
.getEntityBinding( entityDescriptor.getEntityName() );
final InMemoryGenerator identifierGenerator = entityDescriptor.getEntityPersister().getGenerator();
final boolean identityColumn = identifierGenerator instanceof PostInsertIdentifierGenerator;
final Generator identifierGenerator = entityDescriptor.getEntityPersister().getGenerator();
final boolean identityColumn = identifierGenerator.generatedByDatabase();
final boolean hasOptimizer;
if ( identityColumn ) {
hasOptimizer = false;

View File

@ -46,7 +46,7 @@ import org.hibernate.query.spi.QueryEngine;
import org.hibernate.relational.SchemaManager;
import org.hibernate.service.spi.ServiceRegistryImplementor;
import org.hibernate.stat.spi.StatisticsImplementor;
import org.hibernate.tuple.InMemoryGenerator;
import org.hibernate.tuple.Generator;
import org.hibernate.type.Type;
import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.spi.TypeConfiguration;
@ -185,7 +185,7 @@ public class SessionFactoryDelegatingImpl implements SessionFactoryImplementor,
}
@Override
public InMemoryGenerator getGenerator(String rootEntityName) {
public Generator getGenerator(String rootEntityName) {
return delegate.getGenerator( rootEntityName );
}

View File

@ -33,7 +33,7 @@ import org.hibernate.query.sqm.spi.SqmCreationContext;
import org.hibernate.service.spi.ServiceRegistryImplementor;
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
import org.hibernate.stat.spi.StatisticsImplementor;
import org.hibernate.tuple.InMemoryGenerator;
import org.hibernate.tuple.Generator;
import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.spi.TypeConfiguration;
@ -130,7 +130,7 @@ public interface SessionFactoryImplementor
/**
* Get the identifier generator for the hierarchy
*/
InMemoryGenerator getGenerator(String rootEntityName);
Generator getGenerator(String rootEntityName);
EntityNotFoundDelegate getEntityNotFoundDelegate();

View File

@ -34,6 +34,8 @@ import org.hibernate.jpa.event.spi.CallbackRegistry;
import org.hibernate.jpa.event.spi.CallbackRegistryConsumer;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.pretty.MessageHelper;
import org.hibernate.tuple.Generator;
import org.hibernate.tuple.InMemoryGenerator;
import org.hibernate.type.Type;
import org.hibernate.type.TypeHelper;
@ -110,27 +112,30 @@ public abstract class AbstractSaveEventListener<C>
processIfSelfDirtinessTracker( entity, SelfDirtinessTracker::$$_hibernate_clearDirtyAttributes );
EntityPersister persister = source.getEntityPersister( entityName, entity );
Object generatedId = persister.getGenerator().generate( source, entity, null );
if ( generatedId == null ) {
throw new IdentifierGenerationException( "null id generated for: " + entity.getClass() );
}
else if ( generatedId == IdentifierGeneratorHelper.SHORT_CIRCUIT_INDICATOR ) {
return source.getIdentifier( entity );
}
else if ( generatedId == IdentifierGeneratorHelper.POST_INSERT_INDICATOR ) {
return performSave( entity, null, persister, true, context, source, requiresImmediateIdAccess );
final EntityPersister persister = source.getEntityPersister( entityName, entity );
Generator generator = persister.getGenerator();
if ( !generator.generatedByDatabase() ) {
Object generatedId = ( (InMemoryGenerator) generator ).generate( source, entity, null );
if ( generatedId == null ) {
throw new IdentifierGenerationException( "null id generated for: " + entity.getClass() );
}
else if ( generatedId == IdentifierGeneratorHelper.SHORT_CIRCUIT_INDICATOR ) {
return source.getIdentifier( entity );
}
else {
// TODO: define toString()s for generators
if ( LOG.isDebugEnabled() ) {
LOG.debugf(
"Generated identifier: %s, using strategy: %s",
persister.getIdentifierType().toLoggableString( generatedId, source.getFactory() ),
generator.getClass().getName()
);
}
return performSave( entity, generatedId, persister, false, context, source, true );
}
}
else {
// TODO: define toString()s for generators
if ( LOG.isDebugEnabled() ) {
LOG.debugf(
"Generated identifier: %s, using strategy: %s",
persister.getIdentifierType().toLoggableString( generatedId, source.getFactory() ),
persister.getGenerator().getClass().getName()
);
}
return performSave( entity, generatedId, persister, false, context, source, true );
return performSave( entity, null, persister, true, context, source, requiresImmediateIdAccess );
}
}

View File

@ -7,7 +7,11 @@
package org.hibernate.id;
import org.hibernate.boot.model.relational.SqlStringGenerationContext;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.dialect.Dialect;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.type.Type;
import java.util.Properties;
/**
* Basic implementation of the {@link PostInsertIdentifierGenerator} contract.
@ -16,18 +20,22 @@ import org.hibernate.engine.spi.SharedSessionContractImplementor;
*/
public abstract class AbstractPostInsertGenerator
implements PostInsertIdentifierGenerator, BulkInsertionCapableIdentifierGenerator {
@Override
public Object generate(SharedSessionContractImplementor s, Object obj) {
return IdentifierGeneratorHelper.POST_INSERT_INDICATOR;
}
@Override
public boolean supportsBulkInsertionIdentifierGeneration() {
return true;
}
@Override
public String determineBulkInsertionIdentifierGenerationSelectFragment(SqlStringGenerationContext context) {
return null;
}
@Override
public boolean referenceColumnsInSql(Dialect dialect) {
return dialect.getIdentityColumnSupport().hasIdentityInsertKeyword();
}
@Override
public String[] getReferencedColumnValues(Dialect dialect) {
return new String[] { dialect.getIdentityColumnSupport().getIdentityInsertString() };
}
@Override
public void configure(Type type, Properties params, ServiceRegistry serviceRegistry) {}
}

View File

@ -7,7 +7,7 @@
package org.hibernate.id;
import org.hibernate.boot.model.relational.SqlStringGenerationContext;
import org.hibernate.id.factory.spi.StandardGenerator;
import org.hibernate.tuple.Generator;
/**
* Specialized contract for {@link IdentifierGenerator} implementations capable of being used in conjunction
@ -15,7 +15,7 @@ import org.hibernate.id.factory.spi.StandardGenerator;
*
* @author Steve Ebersole
*/
public interface BulkInsertionCapableIdentifierGenerator extends StandardGenerator {
public interface BulkInsertionCapableIdentifierGenerator extends Generator {
/**
* Given the configuration of this generator, is identifier generation as part of bulk insertion supported?
* <p>
@ -24,7 +24,9 @@ public interface BulkInsertionCapableIdentifierGenerator extends StandardGenerat
*
* @return {@code true} if bulk insertions are supported; {@code false} otherwise.
*/
boolean supportsBulkInsertionIdentifierGeneration();
default boolean supportsBulkInsertionIdentifierGeneration() {
return true;
}
/**
* Return the select expression fragment, if any, that generates the identifier values.

View File

@ -15,14 +15,9 @@ import org.hibernate.type.Type;
/**
* An {@link IdentifierGenerator} that supports "configuration".
*
* @deprecated All methods are already defined in {@link IdentifierGenerator}.
* Just implement {@link IdentifierGenerator}.
* @see IdentifierGenerator
*
* @author Gavin King
* @author Steve Ebersole
*/
@Deprecated
public interface Configurable {
/**
* Configure this instance, given the value of parameters

View File

@ -42,5 +42,4 @@ public class IdentityGenerator extends AbstractPostInsertGenerator {
return new BasicSelectingDelegate( persister, dialect );
}
}
}

View File

@ -47,7 +47,7 @@ import org.hibernate.type.Type;
public class IncrementGenerator implements StandardGenerator {
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( IncrementGenerator.class );
private Class returnClass;
private Class<?> returnClass;
private String column;
private List<QualifiedTableName> physicalTableNames;
private String sql;
@ -106,27 +106,27 @@ public class IncrementGenerator implements StandardGenerator {
@Override
public void initialize(SqlStringGenerationContext context) {
StringBuilder buf = new StringBuilder();
StringBuilder union = new StringBuilder();
for ( int i = 0; i < physicalTableNames.size(); i++ ) {
final String tableName = context.format( physicalTableNames.get( i ) );
if ( physicalTableNames.size() > 1 ) {
buf.append( "select max(" ).append( column ).append( ") as mx from " );
union.append( "select max(" ).append( column ).append( ") as mx from " );
}
buf.append( tableName );
union.append( tableName );
if ( i < physicalTableNames.size() - 1 ) {
buf.append( " union " );
union.append( " union " );
}
}
String maxColumn;
if ( physicalTableNames.size() > 1 ) {
buf.insert( 0, "( " ).append( " ) ids_" );
union.insert( 0, "( " ).append( " ) ids_" );
maxColumn = "ids_.mx";
}
else {
maxColumn = column;
}
sql = "select max(" + maxColumn + ") from " + buf.toString();
sql = "select max(" + maxColumn + ") from " + union;
}
private void initializePreviousValueHolder(SharedSessionContractImplementor session) {

View File

@ -8,20 +8,28 @@ package org.hibernate.id;
import org.hibernate.HibernateException;
import org.hibernate.dialect.Dialect;
import org.hibernate.id.factory.spi.StandardGenerator;
import org.hibernate.id.insert.InsertGeneratedIdentifierDelegate;
import org.hibernate.tuple.GenerationTiming;
import org.hibernate.tuple.InDatabaseGenerator;
import static org.hibernate.tuple.GenerationTiming.INSERT;
/**
* @author Gavin King
*/
public interface PostInsertIdentifierGenerator extends StandardGenerator {
public interface PostInsertIdentifierGenerator extends InDatabaseGenerator, Configurable {
InsertGeneratedIdentifierDelegate getInsertGeneratedIdentifierDelegate(
PostInsertIdentityPersister persister,
Dialect dialect,
boolean isGetGeneratedKeysEnabled) throws HibernateException;
@Override
default boolean supportsJdbcBatchInserts() {
default GenerationTiming getGenerationTiming() {
return INSERT;
}
@Override
default boolean writePropertyValue() {
return false;
}
}

View File

@ -5,6 +5,7 @@
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.id;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.mutation.EntityMutationTarget;

View File

@ -91,18 +91,15 @@ public class SelectGenerator extends AbstractPostInsertGenerator {
private final String idSelectString;
public SelectGeneratorDelegate(
PostInsertIdentityPersister persister,
Dialect dialect,
String configuredPropertyName) {
public SelectGeneratorDelegate(PostInsertIdentityPersister persister, Dialect dialect, String propertyName) {
super( persister );
this.persister = persister;
this.dialect = dialect;
this.uniqueKeyPropertyName = determineNameOfPropertyToUse( persister, configuredPropertyName );
this.uniqueKeyPropertyName = determineNameOfPropertyToUse( persister, propertyName );
idSelectString = persister.getSelectByUniqueKeyString( uniqueKeyPropertyName );
uniqueKeyType = persister.getPropertyType( uniqueKeyPropertyName );
idSelectString = persister.getSelectByUniqueKeyString(this.uniqueKeyPropertyName);
uniqueKeyType = persister.getPropertyType(this.uniqueKeyPropertyName);
idType = (BasicType<?>) persister.getIdentifierType();
}
@ -116,37 +113,28 @@ public class SelectGenerator extends AbstractPostInsertGenerator {
}
@Override
public TableInsertBuilder createTableInsertBuilder(BasicEntityIdentifierMapping identifierMapping, Expectation expectation, SessionFactoryImplementor sessionFactory) {
return new TableInsertBuilderStandard(
persister,
persister.getIdentifierTableMapping(),
sessionFactory
);
public TableInsertBuilder createTableInsertBuilder(
BasicEntityIdentifierMapping identifierMapping,
Expectation expectation,
SessionFactoryImplementor sessionFactory) {
return new TableInsertBuilderStandard( persister, persister.getIdentifierTableMapping(), sessionFactory );
}
protected void bindParameters(
Object entity, PreparedStatement ps, SharedSessionContractImplementor session) throws SQLException {
protected void bindParameters(Object entity, PreparedStatement ps, SharedSessionContractImplementor session)
throws SQLException {
Object uniqueKeyValue = persister.getPropertyValue( entity, uniqueKeyPropertyName );
uniqueKeyType.nullSafeSet( ps, uniqueKeyValue, 1, session );
}
@Override
protected Object extractGeneratedValue(
Object entity,
ResultSet rs,
SharedSessionContractImplementor session) throws SQLException {
protected Object extractGeneratedValue(Object entity, ResultSet rs, SharedSessionContractImplementor session)
throws SQLException {
if ( !rs.next() ) {
throw new IdentifierGenerationException(
"the inserted row could not be located by the unique key: " +
uniqueKeyPropertyName
);
throw new IdentifierGenerationException( "the inserted row could not be located by the unique key: "
+ uniqueKeyPropertyName );
}
return idType.getJdbcValueExtractor().extract(
rs,
1,
session
);
return idType.getJdbcValueExtractor().extract( rs, 1, session );
}
}
}

View File

@ -27,7 +27,6 @@ import org.hibernate.boot.model.relational.QualifiedNameParser;
import org.hibernate.boot.model.relational.SqlStringGenerationContext;
import org.hibernate.boot.registry.selector.spi.StrategySelector;
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.engine.jdbc.Size;
@ -43,7 +42,6 @@ import org.hibernate.id.IntegralDataTypeHolder;
import org.hibernate.id.PersistentIdentifierGenerator;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.internal.util.config.ConfigurationHelper;
import org.hibernate.jdbc.AbstractReturningWork;
import org.hibernate.mapping.Column;
import org.hibernate.mapping.PrimaryKey;
@ -58,6 +56,9 @@ import org.jboss.logging.Logger;
import static org.hibernate.cfg.AvailableSettings.ID_DB_STRUCTURE_NAMING_STRATEGY;
import static org.hibernate.internal.log.IncubationLogger.INCUBATION_LOGGER;
import static org.hibernate.internal.util.NullnessHelper.coalesceSuppliedValues;
import static org.hibernate.internal.util.config.ConfigurationHelper.getBoolean;
import static org.hibernate.internal.util.config.ConfigurationHelper.getInt;
import static org.hibernate.internal.util.config.ConfigurationHelper.getString;
/**
* An enhanced version of table-based id generation.
@ -343,12 +344,12 @@ public class TableGenerator implements PersistentIdentifierGenerator {
initialValue = determineInitialValue(parameters);
incrementSize = determineIncrementSize(parameters);
final String optimizationStrategy = ConfigurationHelper.getString(
final String optimizationStrategy = getString(
OPT_PARAM,
parameters,
OptimizerFactory.determineImplicitOptimizerName( incrementSize, parameters)
);
int optimizerInitialValue = ConfigurationHelper.getInt( INITIAL_PARAM, parameters, -1 );
int optimizerInitialValue = getInt( INITIAL_PARAM, parameters, -1 );
optimizer = OptimizerFactory.buildOptimizer(
optimizationStrategy,
identifierType.getReturnedClass(),
@ -373,17 +374,17 @@ public class TableGenerator implements PersistentIdentifierGenerator {
* @return The table name to use.
*/
protected QualifiedName determineGeneratorTableName(Properties params, JdbcEnvironment jdbcEnvironment, ServiceRegistry serviceRegistry) {
final String explicitTableName = ConfigurationHelper.getString( TABLE_PARAM, params );
final String explicitTableName = getString( TABLE_PARAM, params );
if ( StringHelper.isNotEmpty( explicitTableName ) ) {
if ( explicitTableName.contains( "." ) ) {
return QualifiedNameParser.INSTANCE.parse( explicitTableName );
}
else {
final Identifier catalog = jdbcEnvironment.getIdentifierHelper().toIdentifier(
ConfigurationHelper.getString( CATALOG, params )
getString( CATALOG, params )
);
final Identifier schema = jdbcEnvironment.getIdentifierHelper().toIdentifier(
ConfigurationHelper.getString( SCHEMA, params )
getString( SCHEMA, params )
);
return new QualifiedNameParser.NameParts(
catalog,
@ -397,7 +398,7 @@ public class TableGenerator implements PersistentIdentifierGenerator {
final String namingStrategySetting = coalesceSuppliedValues(
() -> {
final String localSetting = ConfigurationHelper.getString( ID_DB_STRUCTURE_NAMING_STRATEGY, params );
final String localSetting = getString( ID_DB_STRUCTURE_NAMING_STRATEGY, params );
if ( localSetting != null ) {
INCUBATION_LOGGER.incubatingSetting( ID_DB_STRUCTURE_NAMING_STRATEGY );
}
@ -405,7 +406,7 @@ public class TableGenerator implements PersistentIdentifierGenerator {
},
() -> {
final ConfigurationService configurationService = serviceRegistry.getService( ConfigurationService.class );
final String globalSetting = ConfigurationHelper.getString( ID_DB_STRUCTURE_NAMING_STRATEGY, configurationService.getSettings() );
final String globalSetting = getString( ID_DB_STRUCTURE_NAMING_STRATEGY, configurationService.getSettings() );
if ( globalSetting != null ) {
INCUBATION_LOGGER.incubatingSetting( ID_DB_STRUCTURE_NAMING_STRATEGY );
}
@ -420,10 +421,10 @@ public class TableGenerator implements PersistentIdentifierGenerator {
);
final Identifier catalog = jdbcEnvironment.getIdentifierHelper().toIdentifier(
ConfigurationHelper.getString( CATALOG, params )
getString( CATALOG, params )
);
final Identifier schema = jdbcEnvironment.getIdentifierHelper().toIdentifier(
ConfigurationHelper.getString( SCHEMA, params )
getString( SCHEMA, params )
);
return namingStrategy.determineTableName( catalog, schema, params, serviceRegistry );
@ -441,7 +442,7 @@ public class TableGenerator implements PersistentIdentifierGenerator {
* @return The name of the segment column
*/
protected String determineSegmentColumnName(Properties params, JdbcEnvironment jdbcEnvironment) {
final String name = ConfigurationHelper.getString( SEGMENT_COLUMN_PARAM, params, DEF_SEGMENT_COLUMN );
final String name = getString( SEGMENT_COLUMN_PARAM, params, DEF_SEGMENT_COLUMN );
return jdbcEnvironment.getIdentifierHelper().toIdentifier( name ).render( jdbcEnvironment.getDialect() );
}
@ -456,7 +457,7 @@ public class TableGenerator implements PersistentIdentifierGenerator {
* @return The name of the value column
*/
protected String determineValueColumnName(Properties params, JdbcEnvironment jdbcEnvironment) {
final String name = ConfigurationHelper.getString( VALUE_COLUMN_PARAM, params, DEF_VALUE_COLUMN );
final String name = getString( VALUE_COLUMN_PARAM, params, DEF_VALUE_COLUMN );
return jdbcEnvironment.getIdentifierHelper().toIdentifier( name ).render( jdbcEnvironment.getDialect() );
}
@ -485,7 +486,7 @@ public class TableGenerator implements PersistentIdentifierGenerator {
* @return The default segment value to use.
*/
protected String determineDefaultSegmentValue(Properties params) {
final boolean preferSegmentPerEntity = ConfigurationHelper.getBoolean( CONFIG_PREFER_SEGMENT_PER_ENTITY, params, false );
final boolean preferSegmentPerEntity = getBoolean( CONFIG_PREFER_SEGMENT_PER_ENTITY, params, false );
final String defaultToUse = preferSegmentPerEntity ? params.getProperty( TABLE ) : DEF_SEGMENT_VALUE;
LOG.usingDefaultIdGeneratorSegmentValue( qualifiedTableName.render(), segmentColumnName, defaultToUse );
return defaultToUse;
@ -501,23 +502,23 @@ public class TableGenerator implements PersistentIdentifierGenerator {
* @return The size of the segment column
*/
protected int determineSegmentColumnSize(Properties params) {
return ConfigurationHelper.getInt( SEGMENT_LENGTH_PARAM, params, DEF_SEGMENT_LENGTH );
return getInt( SEGMENT_LENGTH_PARAM, params, DEF_SEGMENT_LENGTH );
}
protected int determineInitialValue(Properties params) {
return ConfigurationHelper.getInt( INITIAL_PARAM, params, DEFAULT_INITIAL_VALUE );
return getInt( INITIAL_PARAM, params, DEFAULT_INITIAL_VALUE );
}
protected int determineIncrementSize(Properties params) {
return ConfigurationHelper.getInt( INCREMENT_PARAM, params, DEFAULT_INCREMENT_SIZE );
return getInt( INCREMENT_PARAM, params, DEFAULT_INCREMENT_SIZE );
}
@SuppressWarnings("unchecked")
protected String buildSelectQuery(String formattedPhysicalTableName, SqlStringGenerationContext context) {
final String alias = "tbl";
final String query = "select " + StringHelper.qualify( alias, valueColumnName ) +
" from " + formattedPhysicalTableName + ' ' + alias +
" where " + StringHelper.qualify( alias, segmentColumnName ) + "=?";
final String query = "select " + StringHelper.qualify( alias, valueColumnName )
+ " from " + formattedPhysicalTableName + ' ' + alias
+ " where " + StringHelper.qualify( alias, segmentColumnName ) + "=?";
final LockOptions lockOptions = new LockOptions( LockMode.PESSIMISTIC_WRITE );
lockOptions.setAliasSpecificLockMode( alias, LockMode.PESSIMISTIC_WRITE );
final Map updateTargetColumnsMap = Collections.singletonMap( alias, new String[] { valueColumnName } );
@ -525,13 +526,14 @@ public class TableGenerator implements PersistentIdentifierGenerator {
}
protected String buildUpdateQuery(String formattedPhysicalTableName, SqlStringGenerationContext context) {
return "update " + formattedPhysicalTableName +
" set " + valueColumnName + "=? " +
" where " + valueColumnName + "=? and " + segmentColumnName + "=?";
return "update " + formattedPhysicalTableName
+ " set " + valueColumnName + "=? "
+ " where " + valueColumnName + "=? and " + segmentColumnName + "=?";
}
protected String buildInsertQuery(String formattedPhysicalTableName, SqlStringGenerationContext context) {
return "insert into " + formattedPhysicalTableName + " (" + segmentColumnName + ", " + valueColumnName + ") " + " values (?,?)";
return "insert into " + formattedPhysicalTableName
+ " (" + segmentColumnName + ", " + valueColumnName + ") " + " values (?,?)";
}
protected InitCommand generateInsertInitCommand(SqlStringGenerationContext context) {
@ -540,7 +542,9 @@ public class TableGenerator implements PersistentIdentifierGenerator {
if ( storeLastUsedValue ) {
value = initialValue - 1;
}
return new InitCommand( "insert into " + renderedTableName + "(" + segmentColumnName + ", " + valueColumnName + ")" + " values ('" + segmentValue + "'," + ( value ) + ")" );
return new InitCommand( "insert into " + renderedTableName
+ "(" + segmentColumnName + ", " + valueColumnName + ")"
+ " values ('" + segmentValue + "'," + ( value ) + ")" );
}
private IntegralDataTypeHolder makeValue() {
@ -559,93 +563,10 @@ public class TableGenerator implements PersistentIdentifierGenerator {
@Override
public IntegralDataTypeHolder getNextValue() {
return session.getTransactionCoordinator().createIsolationDelegate().delegateWork(
new AbstractReturningWork<IntegralDataTypeHolder>() {
new AbstractReturningWork<>() {
@Override
public IntegralDataTypeHolder execute(Connection connection) throws SQLException {
final IntegralDataTypeHolder value = makeValue();
int rows;
do {
try (PreparedStatement selectPS = prepareStatement(
connection,
selectQuery,
statementLogger,
statsCollector
)) {
selectPS.setString( 1, segmentValue );
final ResultSet selectRS = executeQuery( selectPS, statsCollector );
if ( !selectRS.next() ) {
long initializationValue;
if ( storeLastUsedValue ) {
initializationValue = initialValue - 1;
}
else {
initializationValue = initialValue;
}
value.initialize( initializationValue );
try (PreparedStatement insertPS = prepareStatement(
connection,
insertQuery,
statementLogger,
statsCollector
)) {
LOG.tracef( "binding parameter [%s] - [%s]", 1, segmentValue );
insertPS.setString( 1, segmentValue );
value.bind( insertPS, 2 );
executeUpdate( insertPS, statsCollector );
}
}
else {
int defaultValue;
if ( storeLastUsedValue ) {
defaultValue = 0;
}
else {
defaultValue = 1;
}
value.initialize( selectRS, defaultValue );
}
selectRS.close();
}
catch (SQLException e) {
LOG.unableToReadOrInitHiValue( e );
throw e;
}
try (PreparedStatement updatePS = prepareStatement(
connection,
updateQuery,
statementLogger,
statsCollector
)) {
final IntegralDataTypeHolder updateValue = value.copy();
if ( optimizer.applyIncrementSizeToSourceValues() ) {
updateValue.add( incrementSize );
}
else {
updateValue.increment();
}
updateValue.bind( updatePS, 1 );
value.bind( updatePS, 2 );
updatePS.setString( 3, segmentValue );
rows = executeUpdate( updatePS, statsCollector );
}
catch (SQLException e) {
LOG.unableToUpdateQueryHiValue( physicalTableName.render(), e );
throw e;
}
}
while ( rows == 0 );
accessCount++;
if ( storeLastUsedValue ) {
return value.increment();
}
else {
return value;
}
return nextValue( connection, statementLogger, statsCollector );
}
},
true
@ -660,46 +581,120 @@ public class TableGenerator implements PersistentIdentifierGenerator {
);
}
private IntegralDataTypeHolder nextValue(
Connection connection,
SqlStatementLogger logger,
SessionEventListenerManager listener)
throws SQLException {
final IntegralDataTypeHolder value = makeValue();
int rows;
do {
try ( PreparedStatement selectPS = prepareStatement( connection, selectQuery, logger, listener ) ) {
selectPS.setString( 1, segmentValue );
final ResultSet selectRS = executeQuery( selectPS, listener );
if ( !selectRS.next() ) {
long initializationValue;
if ( storeLastUsedValue ) {
initializationValue = initialValue - 1;
}
else {
initializationValue = initialValue;
}
value.initialize( initializationValue );
try ( PreparedStatement statement = prepareStatement( connection, insertQuery, logger, listener ) ) {
LOG.tracef( "binding parameter [%s] - [%s]", 1, segmentValue );
statement.setString( 1, segmentValue );
value.bind( statement, 2 );
executeUpdate( statement, listener);
}
}
else {
int defaultValue;
if ( storeLastUsedValue ) {
defaultValue = 0;
}
else {
defaultValue = 1;
}
value.initialize( selectRS, defaultValue );
}
selectRS.close();
}
catch (SQLException e) {
LOG.unableToReadOrInitHiValue( e );
throw e;
}
try ( PreparedStatement statement = prepareStatement( connection, updateQuery, logger, listener ) ) {
final IntegralDataTypeHolder updateValue = value.copy();
if ( optimizer.applyIncrementSizeToSourceValues() ) {
updateValue.add( incrementSize );
}
else {
updateValue.increment();
}
updateValue.bind( statement, 1 );
value.bind( statement, 2 );
statement.setString( 3, segmentValue );
rows = executeUpdate( statement, listener );
}
catch (SQLException e) {
LOG.unableToUpdateQueryHiValue( physicalTableName.render(), e );
throw e;
}
}
while ( rows == 0 );
accessCount++;
if ( storeLastUsedValue ) {
return value.increment();
}
else {
return value;
}
}
private PreparedStatement prepareStatement(
Connection connection,
String sql,
SqlStatementLogger statementLogger,
SessionEventListenerManager statsCollector) throws SQLException {
statementLogger.logStatement( sql, FormatStyle.BASIC.getFormatter() );
SqlStatementLogger logger,
SessionEventListenerManager listener) throws SQLException {
logger.logStatement( sql, FormatStyle.BASIC.getFormatter() );
try {
statsCollector.jdbcPrepareStatementStart();
listener.jdbcPrepareStatementStart();
return connection.prepareStatement( sql );
}
finally {
statsCollector.jdbcPrepareStatementEnd();
listener.jdbcPrepareStatementEnd();
}
}
private int executeUpdate(PreparedStatement ps, SessionEventListenerManager statsCollector) throws SQLException {
private int executeUpdate(PreparedStatement ps, SessionEventListenerManager listener) throws SQLException {
try {
statsCollector.jdbcExecuteStatementStart();
listener.jdbcExecuteStatementStart();
return ps.executeUpdate();
}
finally {
statsCollector.jdbcExecuteStatementEnd();
listener.jdbcExecuteStatementEnd();
}
}
private ResultSet executeQuery(PreparedStatement ps, SessionEventListenerManager statsCollector) throws SQLException {
private ResultSet executeQuery(PreparedStatement ps, SessionEventListenerManager listener) throws SQLException {
try {
statsCollector.jdbcExecuteStatementStart();
listener.jdbcExecuteStatementStart();
return ps.executeQuery();
}
finally {
statsCollector.jdbcExecuteStatementEnd();
listener.jdbcExecuteStatementEnd();
}
}
@Override
public void registerExportables(Database database) {
final Dialect dialect = database.getJdbcEnvironment().getDialect();
final Namespace namespace = database.locateNamespace(
qualifiedTableName.getCatalogName(),
qualifiedTableName.getSchemaName()

View File

@ -14,7 +14,7 @@ import org.hibernate.id.IdentifierGenerator;
import org.hibernate.id.factory.spi.GeneratorDefinitionResolver;
import org.hibernate.service.Service;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.tuple.InMemoryGenerator;
import org.hibernate.tuple.Generator;
import org.hibernate.type.Type;
import org.hibernate.type.descriptor.java.JavaType;
@ -50,7 +50,7 @@ public interface IdentifierGeneratorFactory extends Service {
* Create an {@link IdentifierGenerator} based on the given details.
*/
@Incubating
InMemoryGenerator createIdentifierGenerator(
Generator createIdentifierGenerator(
GenerationType generationType,
String generatedValueGeneratorName,
String generatorName,
@ -71,7 +71,7 @@ public interface IdentifierGeneratorFactory extends Service {
* instead
*/
@Deprecated(since = "6.0")
InMemoryGenerator createIdentifierGenerator(String strategy, Type type, Properties parameters);
Generator createIdentifierGenerator(String strategy, Type type, Properties parameters);
/**
* Retrieve the class that will be used as the {@link IdentifierGenerator} for the given strategy.
@ -83,7 +83,7 @@ public interface IdentifierGeneratorFactory extends Service {
* {@link #createIdentifierGenerator(GenerationType, String, String, JavaType, Properties, GeneratorDefinitionResolver)}
*/
@Deprecated(since = "6.0")
Class<? extends InMemoryGenerator> getIdentifierGeneratorClass(String strategy);
Class<? extends Generator> getIdentifierGeneratorClass(String strategy);
/**
* Get the dialect.

View File

@ -20,13 +20,13 @@ import org.hibernate.mapping.Column;
import org.hibernate.mapping.RootClass;
import org.hibernate.mapping.SimpleValue;
import org.hibernate.mapping.Table;
import org.hibernate.tuple.InMemoryGenerator;
import org.hibernate.tuple.Generator;
import java.util.Properties;
public class IdentifierGeneratorUtil {
public static InMemoryGenerator createLegacyIdentifierGenerator(
public static Generator createLegacyIdentifierGenerator(
SimpleValue simpleValue,
IdentifierGeneratorFactory identifierGeneratorFactory,
Dialect dialect,

View File

@ -21,6 +21,7 @@ import org.hibernate.dialect.Dialect;
import org.hibernate.engine.config.spi.ConfigurationService;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
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;
@ -43,7 +44,7 @@ import org.hibernate.resource.beans.internal.FallbackBeanInstanceProducer;
import org.hibernate.resource.beans.internal.Helper;
import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.tuple.InMemoryGenerator;
import org.hibernate.tuple.Generator;
import org.hibernate.type.Type;
import org.hibernate.type.descriptor.java.JavaType;
@ -61,7 +62,7 @@ public class StandardIdentifierGeneratorFactory
implements IdentifierGeneratorFactory, BeanContainer.LifecycleOptions, Serializable {
private final ConcurrentHashMap<GenerationType, GenerationTypeStrategy> generatorTypeStrategyMap = new ConcurrentHashMap<>();
private final ConcurrentHashMap<String, Class<? extends IdentifierGenerator>> legacyGeneratorClassNameMap = new ConcurrentHashMap<>();
private final ConcurrentHashMap<String, Class<? extends Generator>> legacyGeneratorClassNameMap = new ConcurrentHashMap<>();
private final ServiceRegistry serviceRegistry;
private final BeanContainer beanContainer;
@ -169,7 +170,7 @@ public class StandardIdentifierGeneratorFactory
}
}
private void register(String strategy, Class<? extends IdentifierGenerator> generatorClass) {
private void register(String strategy, Class<? extends Generator> generatorClass) {
ID_GEN_FAC_LOGGER.debugf( "Registering IdentifierGenerator strategy [%s] -> [%s]", strategy, generatorClass.getName() );
final Class<?> previous = legacyGeneratorClassNameMap.put( strategy, generatorClass );
if ( previous != null && ID_GEN_FAC_LOGGER.isDebugEnabled() ) {
@ -208,10 +209,10 @@ public class StandardIdentifierGeneratorFactory
}
@Override
public InMemoryGenerator createIdentifierGenerator(String strategy, Type type, Properties parameters) {
public Generator createIdentifierGenerator(String strategy, Type type, Properties parameters) {
try {
final Class<? extends InMemoryGenerator> clazz = getIdentifierGeneratorClass( strategy );
final InMemoryGenerator identifierGenerator;
final Class<? extends Generator> clazz = getIdentifierGeneratorClass( strategy );
final Generator identifierGenerator;
if ( beanContainer == null
|| StandardGenerator.class.isAssignableFrom( clazz )
|| legacyGeneratorClassNameMap.containsKey( strategy ) ) {
@ -223,8 +224,8 @@ public class StandardIdentifierGeneratorFactory
.getBeanInstance();
}
if ( identifierGenerator instanceof IdentifierGenerator ) {
( (IdentifierGenerator) identifierGenerator ).configure( type, parameters, serviceRegistry );
if ( identifierGenerator instanceof Configurable ) {
( (Configurable) identifierGenerator ).configure( type, parameters, serviceRegistry );
}
return identifierGenerator;
}
@ -245,7 +246,7 @@ public class StandardIdentifierGeneratorFactory
}
@Override
public Class<? extends InMemoryGenerator> getIdentifierGeneratorClass(String strategy) {
public Class<? extends Generator> getIdentifierGeneratorClass(String strategy) {
if ( "hilo".equals( strategy ) ) {
throw new UnsupportedOperationException( "Support for 'hilo' generator has been removed" );
}
@ -253,18 +254,18 @@ public class StandardIdentifierGeneratorFactory
? getDialect().getNativeIdentifierGeneratorStrategy()
: strategy;
Class<? extends IdentifierGenerator> generatorClass = legacyGeneratorClassNameMap.get( resolvedStrategy );
Class<? extends Generator> generatorClass = legacyGeneratorClassNameMap.get( resolvedStrategy );
if ( generatorClass != null ) {
return generatorClass;
}
else {
try {
Class<? extends InMemoryGenerator> clazz =
Class<? extends Generator> clazz =
serviceRegistry.getService( ClassLoaderService.class )
.classForName( resolvedStrategy );
if ( !InMemoryGenerator.class.isAssignableFrom( clazz ) ) {
if ( !Generator.class.isAssignableFrom( clazz ) ) {
// in principle, this shouldn't happen, since @GenericGenerator
// constrains the type to subtypes of InMemoryGenerator
// constrains the type to subtypes of Generator
throw new MappingException( clazz.getName() + " does not implement 'InMemoryGenerator'" );
}
return clazz;

View File

@ -51,10 +51,7 @@ public abstract class AbstractReturningDelegate implements InsertGeneratedIdenti
}
@Override
public final Object performInsert(
String insertSql,
SharedSessionContractImplementor session,
Binder binder) {
public final Object performInsert(String insertSql, SharedSessionContractImplementor session, Binder binder) {
try {
// prepare and execute the insert
PreparedStatement insert = prepareStatement( insertSql, session );

View File

@ -15,10 +15,13 @@ import org.hibernate.engine.jdbc.mutation.group.PreparedStatementDetails;
import org.hibernate.engine.jdbc.spi.JdbcCoordinator;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.jdbc.spi.MutationStatementPreparer;
import org.hibernate.engine.jdbc.spi.StatementPreparer;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.id.PostInsertIdentityPersister;
import org.hibernate.pretty.MessageHelper;
import static java.sql.Statement.NO_GENERATED_KEYS;
/**
* Abstract InsertGeneratedIdentifierDelegate implementation where the
* underlying strategy requires a subsequent select after the insert
@ -40,10 +43,8 @@ public abstract class AbstractSelectingDelegate implements InsertGeneratedIdenti
*/
protected abstract String getSelectSQL();
protected void bindParameters(
Object entity,
PreparedStatement ps,
SharedSessionContractImplementor session) throws SQLException {
protected void bindParameters(Object entity, PreparedStatement ps, SharedSessionContractImplementor session)
throws SQLException {
}
/**
@ -51,16 +52,13 @@ public abstract class AbstractSelectingDelegate implements InsertGeneratedIdenti
* from execution of {@link #getSelectSQL()}.
*
*/
protected abstract Object extractGeneratedValue(
Object entity,
ResultSet rs,
SharedSessionContractImplementor session) throws SQLException;
protected abstract Object extractGeneratedValue(Object entity, ResultSet rs, SharedSessionContractImplementor session)
throws SQLException;
@Override
public PreparedStatement prepareStatement(String insertSql, SharedSessionContractImplementor session) {
final JdbcCoordinator jdbcCoordinator = session.getJdbcCoordinator();
final MutationStatementPreparer statementPreparer = jdbcCoordinator.getMutationStatementPreparer();
return statementPreparer.prepareStatement( insertSql, PreparedStatement.NO_GENERATED_KEYS );
final MutationStatementPreparer statementPreparer = session.getJdbcCoordinator().getMutationStatementPreparer();
return statementPreparer.prepareStatement( insertSql, NO_GENERATED_KEYS );
}
@Override
@ -81,10 +79,7 @@ public abstract class AbstractSelectingDelegate implements InsertGeneratedIdenti
// the insert is complete, select the generated id...
final String idSelectSql = getSelectSQL();
final PreparedStatement idSelect = jdbcCoordinator
.getStatementPreparer()
.prepareStatement( idSelectSql );
final PreparedStatement idSelect = jdbcCoordinator.getStatementPreparer().prepareStatement( idSelectSql );
try {
bindParameters( entity, idSelect, session );
@ -118,12 +113,10 @@ public abstract class AbstractSelectingDelegate implements InsertGeneratedIdenti
String insertSQL,
SharedSessionContractImplementor session,
Binder binder) {
StatementPreparer statementPreparer = session.getJdbcCoordinator().getStatementPreparer();
try {
// prepare and execute the insert
PreparedStatement insert = session
.getJdbcCoordinator()
.getStatementPreparer()
.prepareStatement( insertSQL, PreparedStatement.NO_GENERATED_KEYS );
PreparedStatement insert = statementPreparer.prepareStatement( insertSQL, NO_GENERATED_KEYS );
try {
binder.bindValues( insert );
session.getJdbcCoordinator().getResultSetReturn().executeUpdate( insert );
@ -145,10 +138,7 @@ public abstract class AbstractSelectingDelegate implements InsertGeneratedIdenti
try {
//fetch the generated id in a separate query
PreparedStatement idSelect = session
.getJdbcCoordinator()
.getStatementPreparer()
.prepareStatement( selectSQL, false );
PreparedStatement idSelect = statementPreparer.prepareStatement( selectSQL, false );
try {
bindParameters( binder.getEntity(), idSelect, session );
ResultSet rs = session.getJdbcCoordinator().getResultSetReturn().extract( idSelect );

View File

@ -66,10 +66,8 @@ public class BasicSelectingDelegate extends AbstractSelectingDelegate {
}
@Override
protected Object extractGeneratedValue(
Object entity,
ResultSet rs,
SharedSessionContractImplementor session) throws SQLException {
protected Object extractGeneratedValue(Object entity, ResultSet rs, SharedSessionContractImplementor session)
throws SQLException {
return IdentifierGeneratorHelper.getGeneratedIdentity(
rs,
persister.getNavigableRole(),

View File

@ -15,7 +15,6 @@ import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.identity.IdentityColumnSupport;
import org.hibernate.engine.jdbc.spi.JdbcCoordinator;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.jdbc.spi.MutationStatementPreparer;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.id.IdentifierGeneratorHelper;
@ -24,6 +23,8 @@ import org.hibernate.jdbc.Expectation;
import org.hibernate.metamodel.mapping.BasicEntityIdentifierMapping;
import org.hibernate.sql.model.ast.builder.TableInsertBuilder;
import static java.sql.Statement.NO_GENERATED_KEYS;
/**
* Delegate for dealing with IDENTITY columns where the dialect supports returning
* the generated IDENTITY value directly from the insert statement.
@ -97,10 +98,6 @@ public class InsertReturningDelegate extends AbstractReturningDelegate {
@Override
public PreparedStatement prepareStatement(String insertSql, SharedSessionContractImplementor session) {
final MutationStatementPreparer statementPreparer = session
.getJdbcCoordinator()
.getMutationStatementPreparer();
return statementPreparer.prepareStatement( insertSql, PreparedStatement.NO_GENERATED_KEYS );
return session.getJdbcCoordinator().getMutationStatementPreparer().prepareStatement( insertSql, NO_GENERATED_KEYS );
}
}

View File

@ -28,6 +28,7 @@ public class InsertSelectIdentityInsert extends IdentifierGeneratingInsert {
}
public String toStatementString() {
return getDialect().getIdentityColumnSupport().appendIdentitySelectToInsert( identityColumnName, super.toStatementString() );
return getDialect().getIdentityColumnSupport()
.appendIdentitySelectToInsert( identityColumnName, super.toStatementString() );
}
}

View File

@ -124,7 +124,7 @@ import org.hibernate.service.spi.SessionFactoryServiceRegistryFactory;
import org.hibernate.stat.spi.StatisticsImplementor;
import org.hibernate.tool.schema.spi.DelayedDropAction;
import org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator;
import org.hibernate.tuple.InMemoryGenerator;
import org.hibernate.tuple.Generator;
import org.hibernate.type.Type;
import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.spi.TypeConfiguration;
@ -184,7 +184,7 @@ public class SessionFactoryImpl implements SessionFactoryImplementor {
private volatile DelayedDropAction delayedDropAction;
// todo : move to MetamodelImpl
private final transient Map<String, InMemoryGenerator> identifierGenerators;
private final transient Map<String, Generator> identifierGenerators;
private final transient Map<String, FilterDefinition> filters;
private final transient Map<String, FetchProfile> fetchProfiles;
@ -294,7 +294,7 @@ public class SessionFactoryImpl implements SessionFactoryImplementor {
//Generators:
this.identifierGenerators = new HashMap<>();
bootMetamodel.getEntityBindings().stream().filter( model -> !model.isInherited() ).forEach( model -> {
final InMemoryGenerator generator = model.getIdentifier().createGenerator(
final Generator generator = model.getIdentifier().createGenerator(
bootstrapContext.getIdentifierGeneratorFactory(),
jdbcServices.getJdbcEnvironment().getDialect(),
(RootClass) model
@ -994,7 +994,7 @@ public class SessionFactoryImpl implements SessionFactoryImplementor {
}
@Deprecated
public InMemoryGenerator getGenerator(String rootEntityName) {
public Generator getGenerator(String rootEntityName) {
return identifierGenerators.get( rootEntityName );
}

View File

@ -28,12 +28,13 @@ import org.hibernate.engine.spi.PersistentAttributeInterceptor;
import org.hibernate.engine.transaction.internal.jta.JtaStatusHelper;
import org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform;
import org.hibernate.event.spi.EventSource;
import org.hibernate.id.IdentifierGeneratorHelper;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.pretty.MessageHelper;
import org.hibernate.proxy.HibernateProxy;
import org.hibernate.proxy.LazyInitializer;
import org.hibernate.tuple.Generator;
import org.hibernate.tuple.InMemoryGenerator;
import org.hibernate.tuple.entity.EntityMetamodel;
import jakarta.transaction.SystemException;
@ -94,25 +95,27 @@ public class StatelessSessionImpl extends AbstractSharedSessionContract implemen
@Override
public Object insert(String entityName, Object entity) {
checkOpen();
EntityPersister persister = getEntityPersister( entityName, entity );
Object id = persister.getGenerator().generate( this, entity, null );
Object[] state = persister.getValues( entity );
if ( persister.isVersioned() ) {
boolean substitute = Versioning.seedVersion(
state,
persister.getVersionProperty(),
persister.getVersionMapping(),
this
);
if ( substitute ) {
persister.setValues( entity, state );
final EntityPersister persister = getEntityPersister( entityName, entity );
final Object id;
final Object[] state = persister.getValues( entity );
Generator generator = persister.getGenerator();
if ( !generator.generatedByDatabase() ) {
id = ( (InMemoryGenerator) generator).generate( this, entity, null );
if ( persister.isVersioned() ) {
boolean substitute = Versioning.seedVersion(
state,
persister.getVersionProperty(),
persister.getVersionMapping(),
this
);
if ( substitute ) {
persister.setValues( entity, state );
}
}
}
if ( id == IdentifierGeneratorHelper.POST_INSERT_INDICATOR ) {
id = persister.insert( state, entity, this );
persister.insert( id, state, entity, this );
}
else {
persister.insert( id, state, entity, this );
id = persister.insert( state, entity, this );
}
persister.setIdentifier( entity, id, this );
return id;

View File

@ -28,12 +28,14 @@ import org.hibernate.dialect.Dialect;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.id.CompositeNestedGeneratedValueGenerator;
import org.hibernate.id.IdentifierGenerator;
import org.hibernate.id.IdentifierGeneratorHelper;
import org.hibernate.id.factory.IdentifierGeneratorFactory;
import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.internal.util.collections.JoinedIterator;
import org.hibernate.metamodel.spi.EmbeddableInstantiator;
import org.hibernate.property.access.spi.Setter;
import org.hibernate.tuple.Generator;
import org.hibernate.tuple.InMemoryGenerator;
import org.hibernate.type.ComponentType;
import org.hibernate.type.EmbeddedComponentType;
@ -72,7 +74,7 @@ public class Component extends SimpleValue implements MetaAttributable, Sortable
// lazily computed based on 'properties' field: invalidate by setting to null when properties are modified
private transient List<Column> cachedColumns;
private transient InMemoryGenerator builtIdentifierGenerator;
private transient Generator builtIdentifierGenerator;
public Component(MetadataBuildingContext metadata, PersistentClass owner) throws MappingException {
this( metadata, owner.getTable(), owner );
@ -414,7 +416,7 @@ public class Component extends SimpleValue implements MetaAttributable, Sortable
}
@Override
public InMemoryGenerator createGenerator(
public Generator createGenerator(
IdentifierGeneratorFactory identifierGeneratorFactory,
Dialect dialect,
RootClass rootClass) throws MappingException {
@ -428,7 +430,7 @@ public class Component extends SimpleValue implements MetaAttributable, Sortable
return builtIdentifierGenerator;
}
private InMemoryGenerator buildIdentifierGenerator(
private Generator buildIdentifierGenerator(
IdentifierGeneratorFactory identifierGeneratorFactory,
Dialect dialect,
RootClass rootClass) throws MappingException {
@ -470,11 +472,10 @@ public class Component extends SimpleValue implements MetaAttributable, Sortable
if ( !DEFAULT_ID_GEN_STRATEGY.equals( value.getIdentifierGeneratorStrategy() ) ) {
// skip any 'assigned' generators, they would have been handled by
// the StandardGenerationContextLocator
generator.addGeneratedValuePlan(
new ValueGenerationPlan(
value.createGenerator( identifierGeneratorFactory, dialect, rootClass ),
injector( property, attributeDeclarer )
)
Generator subgenerator = value.createGenerator( identifierGeneratorFactory, dialect, rootClass );
generator.addGeneratedValuePlan( new ValueGenerationPlan(
subgenerator,
injector( property, attributeDeclarer ) )
);
}
}
@ -512,11 +513,11 @@ public class Component extends SimpleValue implements MetaAttributable, Sortable
}
public static class ValueGenerationPlan implements CompositeNestedGeneratedValueGenerator.GenerationPlan {
private final InMemoryGenerator subGenerator;
private final Generator subGenerator;
private final Setter injector;
public ValueGenerationPlan(
InMemoryGenerator subGenerator,
Generator subGenerator,
Setter injector) {
this.subGenerator = subGenerator;
this.injector = injector;
@ -524,7 +525,13 @@ public class Component extends SimpleValue implements MetaAttributable, Sortable
@Override
public void execute(SharedSessionContractImplementor session, Object incomingObject, Object injectionContext) {
injector.set( injectionContext, subGenerator.generate( session, incomingObject, null ) );
if ( !subGenerator.generatedByDatabase() ) {
Object generatedId = ( (InMemoryGenerator) subGenerator ).generate( session, incomingObject, null );
injector.set( injectionContext, generatedId );
}
else {
injector.set( injectionContext, IdentifierGeneratorHelper.POST_INSERT_INDICATOR );
}
}
@Override

View File

@ -9,6 +9,7 @@ package org.hibernate.mapping;
import org.hibernate.dialect.Dialect;
import org.hibernate.id.IdentifierGenerator;
import org.hibernate.id.factory.IdentifierGeneratorFactory;
import org.hibernate.tuple.Generator;
import org.hibernate.tuple.InMemoryGenerator;
/**
@ -29,7 +30,7 @@ public interface KeyValue extends Value {
boolean isUpdateable();
InMemoryGenerator createGenerator(
Generator createGenerator(
IdentifierGeneratorFactory identifierGeneratorFactory,
Dialect dialect,
RootClass rootClass);

View File

@ -47,7 +47,7 @@ import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.metamodel.model.convert.spi.JpaAttributeConverter;
import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.tuple.InMemoryGenerator;
import org.hibernate.tuple.Generator;
import org.hibernate.type.Type;
import org.hibernate.type.descriptor.JdbcTypeNameMapper;
import org.hibernate.type.descriptor.java.JavaType;
@ -101,8 +101,7 @@ public abstract class SimpleValue implements KeyValue {
private Type type;
private IdentifierGeneratorCreator customIdGeneratorCreator;
private GeneratorCreator customGeneratorCreator;
private InMemoryGenerator generator;
private Generator generator;
public SimpleValue(MetadataBuildingContext buildingContext) {
this.buildingContext = buildingContext;
@ -379,41 +378,24 @@ public abstract class SimpleValue implements KeyValue {
return customIdGeneratorCreator;
}
public GeneratorCreator getCustomGeneratorCreator() {
return customGeneratorCreator;
}
public void setCustomGeneratorCreator(GeneratorCreator customGeneratorCreator) {
this.customGeneratorCreator = customGeneratorCreator;
}
@Override
public InMemoryGenerator createGenerator(
public Generator createGenerator(
IdentifierGeneratorFactory identifierGeneratorFactory,
Dialect dialect,
RootClass rootClass) throws MappingException {
if ( generator != null ) {
return generator;
}
if ( customIdGeneratorCreator != null ) {
else if ( customIdGeneratorCreator != null ) {
generator = customIdGeneratorCreator.createGenerator(
new IdGeneratorCreationContext( identifierGeneratorFactory, null, null, rootClass )
);
return generator;
}
else if ( customGeneratorCreator != null ) {
// we may as well allow this, so you don't have to annotate generator
// annotations twice, with @IdGeneratorType and @ValueGenerationType
//TODO: this typecast is ugly ... throw a better exception at least
generator = (InMemoryGenerator) customGeneratorCreator.createGenerator(
new IdGeneratorCreationContext( identifierGeneratorFactory, null, null, rootClass )
);
else {
generator = createLegacyIdentifierGenerator(this, identifierGeneratorFactory, dialect, null, null, rootClass );
return generator;
}
generator = createLegacyIdentifierGenerator(this, identifierGeneratorFactory, dialect, null, null, rootClass );
return generator;
}
public boolean isUpdateable() {

View File

@ -128,6 +128,7 @@ import org.hibernate.sql.model.jdbc.JdbcDeleteMutation;
import org.hibernate.sql.model.jdbc.JdbcMutationOperation;
import org.hibernate.sql.results.graph.DomainResult;
import org.hibernate.sql.results.internal.SqlSelectionImpl;
import org.hibernate.tuple.Generator;
import org.hibernate.tuple.InMemoryGenerator;
import org.hibernate.type.CollectionType;
import org.hibernate.type.CompositeType;
@ -510,14 +511,7 @@ public abstract class AbstractCollectionPersister
Column col = idColl.getIdentifier().getColumns().get(0);
identifierColumnName = col.getQuotedName( dialect );
identifierColumnAlias = col.getAlias( dialect );
identifierGenerator = idColl.getIdentifier().createGenerator(
creationContext.getBootstrapContext().getIdentifierGeneratorFactory(),
factory.getJdbcServices().getDialect(),
null
);
if ( identifierGenerator instanceof IdentifierGenerator ) {
( (IdentifierGenerator) identifierGenerator ).initialize( creationContext.getSessionFactory().getSqlStringGenerationContext() );
}
identifierGenerator = createGenerator( creationContext, idColl );
}
else {
identifierType = null;
@ -629,6 +623,21 @@ public abstract class AbstractCollectionPersister
tableMapping = buildCollectionTableMapping( collectionBootDescriptor, qualifiedTableName );
}
private InMemoryGenerator createGenerator(RuntimeModelCreationContext context, IdentifierCollection collection) {
final Generator generator = collection.getIdentifier().createGenerator(
context.getBootstrapContext().getIdentifierGeneratorFactory(),
factory.getJdbcServices().getDialect(),
null
);
if ( generator.generatedByDatabase() ) {
throw new MappingException("must be an InMemoryGenerator"); //TODO fix message
}
if ( generator instanceof IdentifierGenerator ) {
( (IdentifierGenerator) generator ).initialize( context.getSessionFactory().getSqlStringGenerationContext() );
}
return (InMemoryGenerator) generator;
}
@Override
public NavigableRole getNavigableRole() {
return navigableRole;

View File

@ -2773,8 +2773,8 @@ public abstract class AbstractEntityPersister
&& generator.getGenerationTiming().includesUpdate()
&& generator.generatedByDatabase() ) {
final InDatabaseGenerator databaseGenerator = (InDatabaseGenerator) generator;
if ( databaseGenerator.referenceColumnsInSql() ) {
final Dialect dialect = getFactory().getJdbcServices().getDialect();
final Dialect dialect = getFactory().getJdbcServices().getDialect();
if ( databaseGenerator.referenceColumnsInSql(dialect) ) {
update.addColumns(
getPropertyColumnNames(index),
SINGLE_TRUE,
@ -3179,7 +3179,7 @@ public abstract class AbstractEntityPersister
private void doLateInit() {
if ( isIdentifierAssignedByInsert() ) {
final PostInsertIdentifierGenerator idGenerator = (PostInsertIdentifierGenerator) getIdentifierGenerator();
final PostInsertIdentifierGenerator idGenerator = (PostInsertIdentifierGenerator) getGenerator();
identityDelegate = idGenerator.getInsertGeneratedIdentifierDelegate(
this,
getFactory().getJdbcServices().getDialect(),
@ -3944,7 +3944,7 @@ public abstract class AbstractEntityPersister
}
@Override
public InMemoryGenerator getGenerator() {
public Generator getGenerator() {
return entityMetamodel.getIdentifierProperty().getGenerator();
}
@ -4344,7 +4344,7 @@ public abstract class AbstractEntityPersister
Object currentId,
Object currentVersion,
SharedSessionContractImplementor session) {
if ( entityMetamodel.getIdentifierProperty().getIdentifierGenerator() instanceof Assigned ) {
if ( entityMetamodel.getIdentifierProperty().getGenerator() instanceof Assigned ) {
return;
}

View File

@ -45,7 +45,7 @@ import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
import org.hibernate.sql.ast.spi.SqlAliasStemHelper;
import org.hibernate.sql.ast.tree.from.RootTableGroupProducer;
import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.tuple.InMemoryGenerator;
import org.hibernate.tuple.Generator;
import org.hibernate.tuple.entity.EntityMetamodel;
import org.hibernate.type.BasicType;
import org.hibernate.type.Type;
@ -459,7 +459,7 @@ public interface EntityPersister
@Deprecated
IdentifierGenerator getIdentifierGenerator();
default InMemoryGenerator getGenerator() {
default Generator getGenerator() {
return getIdentifierGenerator();
}

View File

@ -51,6 +51,11 @@ public abstract class AbstractMutationCoordinator {
return factory;
}
protected Dialect dialect() {
return factory().getJdbcServices().getDialect();
}
protected MutationOperationGroup createOperationGroup(ValuesAnalysis valuesAnalysis, MutationGroup mutationGroup) {
if ( mutationGroup.getNumberOfTableMutations() == 0 ) {
return new MutationOperationGroupNone( mutationGroup.getMutationType(), mutationGroup.getMutationTarget() );

View File

@ -10,6 +10,7 @@ import java.util.ArrayList;
import java.util.List;
import org.hibernate.Internal;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.jdbc.batch.internal.BasicBatchKey;
import org.hibernate.engine.jdbc.mutation.JdbcValueBindings;
import org.hibernate.engine.jdbc.mutation.MutationExecutor;
@ -106,7 +107,7 @@ public class InsertCoordinator extends AbstractMutationCoordinator {
if ( generator != null
&& !generator.generatedByDatabase()
&& generator.getGenerationTiming().includesInsert() ) {
values[i] = ( (InMemoryGenerator) generator).generate( session, entity, values[i] );
values[i] = ( (InMemoryGenerator) generator ).generate( session, entity, values[i] );
entityPersister().setPropertyValue( entity, i, values[i] );
}
}
@ -393,7 +394,7 @@ public class InsertCoordinator extends AbstractMutationCoordinator {
if ( !attributeInclusions[ attributeIndex ] ) {
final Generator generator = attributeMapping.getGenerator();
if ( isValueGenerationInSql( generator ) ) {
if ( isValueGenerationInSql( generator, factory().getJdbcServices().getDialect()) ) {
handleValueGeneration( attributeMapping, insertGroupBuilder, (InDatabaseGenerator) generator );
}
continue;
@ -435,10 +436,10 @@ public class InsertCoordinator extends AbstractMutationCoordinator {
} );
}
private static boolean isValueGenerationInSql(Generator generator) {
private static boolean isValueGenerationInSql(Generator generator, Dialect dialect) {
return generator != null
&& generator.getGenerationTiming().includesInsert()
&& generator.generatedByDatabase()
&& ( (InDatabaseGenerator) generator ).referenceColumnsInSql();
&& ( (InDatabaseGenerator) generator ).referenceColumnsInSql(dialect);
}
}

View File

@ -14,6 +14,7 @@ import java.util.Set;
import org.hibernate.HibernateException;
import org.hibernate.Internal;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.OptimisticLockStyle;
import org.hibernate.engine.jdbc.batch.internal.BasicBatchKey;
import org.hibernate.engine.jdbc.batch.spi.BatchKey;
@ -200,8 +201,10 @@ public class UpdateCoordinatorStandard extends AbstractMutationCoordinator imple
}
}
final InclusionChecker updateabilityChecker =
(position, attribute) -> isValueGenerationInSql( attribute.getGenerator() ) || attributeUpdateability[ position ];
(position, attribute) -> isValueGenerationInSql( attribute.getGenerator(), dialect() )
|| attributeUpdateability[ position ];
final InclusionChecker dirtinessChecker = (position, attribute) -> {
if ( !attributeUpdateability[ position ] ) {
@ -332,18 +335,18 @@ public class UpdateCoordinatorStandard extends AbstractMutationCoordinator imple
return false;
}
private boolean isValueGenerationInSql(Generator generator) {
private boolean isValueGenerationInSql(Generator generator, Dialect dialect) {
return generator != null
&& generator.getGenerationTiming().includesUpdate()
&& generator.generatedByDatabase()
&& ((InDatabaseGenerator) generator).referenceColumnsInSql();
&& ((InDatabaseGenerator) generator).referenceColumnsInSql(dialect);
}
private boolean isValueGenerationInSqlNoWrite(Generator generator) {
private boolean isValueGenerationInSqlNoWrite(Generator generator, Dialect dialect) {
return generator != null
&& generator.getGenerationTiming().includesUpdate()
&& generator.generatedByDatabase()
&& ((InDatabaseGenerator) generator).referenceColumnsInSql()
&& ((InDatabaseGenerator) generator).referenceColumnsInSql(dialect)
&& !((InDatabaseGenerator) generator).writePropertyValue();
}
@ -696,7 +699,7 @@ public class UpdateCoordinatorStandard extends AbstractMutationCoordinator imple
// apply the new values
final boolean includeInSet;
if ( isValueGenerationInSqlNoWrite( attributeMapping.getGenerator() ) ) {
if ( isValueGenerationInSqlNoWrite( attributeMapping.getGenerator(), dialect() ) ) {
// we applied `#getDatabaseGeneratedReferencedColumnValue` earlier
includeInSet = false;
}
@ -930,7 +933,7 @@ public class UpdateCoordinatorStandard extends AbstractMutationCoordinator imple
assert updateValuesAnalysis.tablesNeedingUpdate.contains( tableMapping );
final Generator generator = attributeMapping.getGenerator();
if ( isValueGenerationInSql( generator ) ) {
if ( isValueGenerationInSql( generator, dialect() ) ) {
handleValueGeneration( attributeMapping, updateGroupBuilder, (InDatabaseGenerator) generator );
}
else if ( versionMapping != null
@ -1360,7 +1363,7 @@ public class UpdateCoordinatorStandard extends AbstractMutationCoordinator imple
null,
null,
null,
(index,attribute) -> isValueGenerationInSql( attribute.getGenerator() )
(index,attribute) -> isValueGenerationInSql( attribute.getGenerator(), dialect() )
|| entityPersister().getPropertyUpdateability()[index],
(index,attribute) -> {
final OptimisticLockStyle optimisticLockStyle = entityPersister().optimisticLockStyle();

View File

@ -107,6 +107,7 @@ import org.hibernate.query.sqm.tree.update.SqmAssignment;
import org.hibernate.query.sqm.tree.update.SqmUpdateStatement;
import org.hibernate.sql.results.internal.TupleMetadata;
import org.hibernate.sql.results.spi.ListResultsConsumer;
import org.hibernate.tuple.Generator;
import org.hibernate.tuple.InMemoryGenerator;
import static org.hibernate.jpa.HibernateHints.HINT_CACHEABLE;
@ -838,7 +839,7 @@ public class QuerySqmImpl<R>
boolean useMultiTableInsert = entityDescriptor.isMultiTable();
if ( !useMultiTableInsert && !isSimpleValuesInsert( sqmInsert, entityDescriptor ) ) {
final InMemoryGenerator identifierGenerator = entityDescriptor.getGenerator();
final Generator identifierGenerator = entityDescriptor.getGenerator();
if ( identifierGenerator instanceof BulkInsertionCapableIdentifierGenerator
&& identifierGenerator instanceof OptimizableGenerator ) {
final Optimizer optimizer = ( (OptimizableGenerator) identifierGenerator ).getOptimizer();

View File

@ -94,7 +94,7 @@ import org.hibernate.sql.results.graph.DomainResult;
import org.hibernate.sql.results.graph.basic.BasicResult;
import org.hibernate.sql.results.internal.SqlSelectionImpl;
import org.hibernate.sql.results.spi.ListResultsConsumer;
import org.hibernate.tuple.InMemoryGenerator;
import org.hibernate.tuple.Generator;
import org.hibernate.type.spi.TypeConfiguration;
/**
@ -273,7 +273,7 @@ public class CteInsertHandler implements InsertHandler {
rowNumberColumn
);
}
if ( !assignsId && entityDescriptor.getGenerator() instanceof PostInsertIdentifierGenerator ) {
if ( !assignsId && entityDescriptor.getGenerator().generatedByDatabase() ) {
querySpec.getSelectClause().addSqlSelection(
new SqlSelectionImpl(
1,
@ -337,7 +337,7 @@ public class CteInsertHandler implements InsertHandler {
processingStateStack.push( oldState );
sqmConverter.pruneTableGroupJoins();
if ( !assignsId && entityDescriptor.getGenerator() instanceof PostInsertIdentifierGenerator ) {
if ( !assignsId && entityDescriptor.getGenerator().generatedByDatabase() ) {
// Add the row number to the assignments
final CteColumn rowNumberColumn = cteTable.getCteColumns()
.get( cteTable.getCteColumns().size() - 1 );
@ -581,7 +581,7 @@ public class CteInsertHandler implements InsertHandler {
statement.addCteStatement( entityCte );
}
}
else if ( !assignsId && entityDescriptor.getGenerator() instanceof PostInsertIdentifierGenerator ) {
else if ( !assignsId && entityDescriptor.getGenerator().generatedByDatabase() ) {
final String baseTableName = "base_" + entityCteTable.getTableExpression();
final CteStatement baseEntityCte = new CteStatement(
entityCteTable.withName( baseTableName ),
@ -775,9 +775,10 @@ public class CteInsertHandler implements InsertHandler {
true
);
final InMemoryGenerator identifierGenerator = entityDescriptor.getEntityPersister().getGenerator();
final Generator identifierGenerator = entityDescriptor.getEntityPersister().getGenerator();
final List<Map.Entry<List<CteColumn>, Assignment>> tableAssignments = assignmentsByTable.get( rootTableReference );
if ( ( tableAssignments == null || tableAssignments.isEmpty() ) && !( identifierGenerator instanceof PostInsertIdentifierGenerator ) ) {
if ( ( tableAssignments == null || tableAssignments.isEmpty() )
&& !( identifierGenerator.generatedByDatabase() ) ) {
throw new IllegalStateException( "There must be at least a single root table assignment" );
}
@ -805,7 +806,7 @@ public class CteInsertHandler implements InsertHandler {
final QuerySpec insertSelectSpec = new QuerySpec( true );
CteStatement finalCteStatement = null;
final CteTable dmlResultCte;
if ( i == 0 && !assignsId && identifierGenerator instanceof PostInsertIdentifierGenerator ) {
if ( i == 0 && !assignsId && identifierGenerator.generatedByDatabase() ) {
// Special handling for identity generation
final String cteTableName = getCteTableName( tableExpression, "base_" );
if ( statement.getCteStatement( cteTableName ) != null ) {
@ -1074,7 +1075,7 @@ public class CteInsertHandler implements InsertHandler {
if ( finalCteStatement != null ) {
statement.addCteStatement( finalCteStatement );
}
if ( i == 0 && !assignsId && identifierGenerator instanceof PostInsertIdentifierGenerator ) {
if ( i == 0 && !assignsId && identifierGenerator.generatedByDatabase() ) {
// Special handling for identity generation
statement.addCteStatement( queryCte );
}

View File

@ -73,6 +73,7 @@ import org.hibernate.sql.exec.spi.JdbcParameterBindings;
import org.hibernate.sql.results.graph.basic.BasicFetch;
import org.hibernate.sql.results.internal.SqlSelectionImpl;
import org.hibernate.sql.results.spi.ListResultsConsumer;
import org.hibernate.tuple.Generator;
import org.hibernate.tuple.InMemoryGenerator;
import org.hibernate.type.descriptor.ValueBinder;
@ -301,12 +302,12 @@ public class InsertExecutionDelegate implements TableBasedInsertHandler.Executio
true
);
final InMemoryGenerator identifierGenerator = entityDescriptor.getEntityPersister().getGenerator();
final Generator generator = entityDescriptor.getEntityPersister().getGenerator();
final List<Assignment> assignments = assignmentsByTable.get( updatingTableReference );
if ( ( assignments == null || assignments.isEmpty() )
&& !( identifierGenerator instanceof PostInsertIdentifierGenerator )
&& ( !( identifierGenerator instanceof BulkInsertionCapableIdentifierGenerator )
|| ( (BulkInsertionCapableIdentifierGenerator) identifierGenerator ).supportsBulkInsertionIdentifierGeneration() ) ) {
&& !generator.generatedByDatabase()
&& ( !( generator instanceof BulkInsertionCapableIdentifierGenerator )
|| ( (BulkInsertionCapableIdentifierGenerator) generator ).supportsBulkInsertionIdentifierGeneration() ) ) {
throw new IllegalStateException( "There must be at least a single root table assignment" );
}
@ -352,7 +353,7 @@ public class InsertExecutionDelegate implements TableBasedInsertHandler.Executio
}
final JdbcServices jdbcServices = sessionFactory.getJdbcServices();
final Map<Object, Object> entityTableToRootIdentity;
if ( identifierGenerator instanceof PostInsertIdentifierGenerator ) {
if ( generator.generatedByDatabase() ) {
final BasicEntityIdentifierMapping identifierMapping = (BasicEntityIdentifierMapping) entityDescriptor.getIdentifierMapping();
final QuerySpec idSelectQuerySpec = new QuerySpec( true );
idSelectQuerySpec.getFromClause().addRoot( temporaryTableGroup );
@ -413,10 +414,9 @@ public class InsertExecutionDelegate implements TableBasedInsertHandler.Executio
// if the target paths don't already contain the id, and we need identifier generation,
// then we load update rows from the temporary table with the generated identifiers,
// to then insert into the target tables in once statement
if ( needsIdentifierGeneration( identifierGenerator )
&& insertStatement.getTargetColumns()
.stream()
.noneMatch( c -> keyColumns[0].equals( c.getColumnExpression() ) ) ) {
if ( needsIdentifierGeneration( generator )
&& insertStatement.getTargetColumns().stream()
.noneMatch( c -> keyColumns[0].equals( c.getColumnExpression() ) ) ) {
final BasicEntityIdentifierMapping identifierMapping = (BasicEntityIdentifierMapping) entityDescriptor.getIdentifierMapping();
final JdbcParameter rowNumber = new JdbcParameterImpl( identifierMapping.getJdbcMapping() );
@ -507,7 +507,7 @@ public class InsertExecutionDelegate implements TableBasedInsertHandler.Executio
rootIdentity,
new JdbcParameterBindingImpl(
identifierMapping.getJdbcMapping(),
identifierGenerator.generate( executionContext.getSession(), null, null )
( (InMemoryGenerator) generator ).generate( executionContext.getSession(), null, null )
)
);
jdbcServices.getJdbcMutationExecutor().execute(
@ -555,10 +555,10 @@ public class InsertExecutionDelegate implements TableBasedInsertHandler.Executio
.buildInsertTranslator( sessionFactory, insertStatement )
.translate( null, executionContext.getQueryOptions() );
if ( identifierGenerator instanceof PostInsertIdentifierGenerator ) {
final PostInsertIdentifierGenerator generator = (PostInsertIdentifierGenerator) identifierGenerator;
if ( generator.generatedByDatabase() ) {
final PostInsertIdentifierGenerator postInsertGenerator = (PostInsertIdentifierGenerator) generator;
final boolean generatedKeysEnabled = sessionFactory.getSessionFactoryOptions().isGetGeneratedKeysEnabled();
final InsertGeneratedIdentifierDelegate identifierDelegate = generator.getInsertGeneratedIdentifierDelegate(
final InsertGeneratedIdentifierDelegate identifierDelegate = postInsertGenerator.getInsertGeneratedIdentifierDelegate(
(PostInsertIdentityPersister) entityDescriptor.getEntityPersister(),
jdbcServices.getDialect(),
generatedKeysEnabled
@ -651,7 +651,7 @@ public class InsertExecutionDelegate implements TableBasedInsertHandler.Executio
}
}
private boolean needsIdentifierGeneration(InMemoryGenerator identifierGenerator) {
private boolean needsIdentifierGeneration(Generator identifierGenerator) {
if ( !( identifierGenerator instanceof OptimizableGenerator ) ) {
return false;
}
@ -718,9 +718,9 @@ public class InsertExecutionDelegate implements TableBasedInsertHandler.Executio
}
final String targetKeyColumnName = keyColumns[0];
final AbstractEntityPersister entityPersister = (AbstractEntityPersister) entityDescriptor.getEntityPersister();
final InMemoryGenerator identifierGenerator = entityPersister.getGenerator();
final Generator identifierGenerator = entityPersister.getGenerator();
final boolean needsKeyInsert;
if ( identifierGenerator instanceof PostInsertIdentifierGenerator ) {
if ( identifierGenerator.generatedByDatabase() ) {
needsKeyInsert = true;
}
else if ( identifierGenerator instanceof OptimizableGenerator ) {

View File

@ -52,6 +52,7 @@ import org.hibernate.sql.ast.tree.update.Assignment;
import org.hibernate.sql.exec.internal.JdbcParameterImpl;
import org.hibernate.sql.exec.spi.ExecutionContext;
import org.hibernate.sql.results.internal.SqlSelectionImpl;
import org.hibernate.tuple.Generator;
import org.hibernate.tuple.InMemoryGenerator;
import org.hibernate.type.BasicType;
@ -254,7 +255,7 @@ public class TableBasedInsertHandler implements InsertHandler {
}
else {
// Add the row number column if there is one
final InMemoryGenerator generator = entityDescriptor.getGenerator();
final Generator generator = entityDescriptor.getGenerator();
final BasicType<?> rowNumberType;
if ( generator instanceof OptimizableGenerator ) {
final Optimizer optimizer = ( (OptimizableGenerator) generator ).getOptimizer();

View File

@ -45,7 +45,6 @@ import org.hibernate.graph.spi.AppliedGraph;
import org.hibernate.id.BulkInsertionCapableIdentifierGenerator;
import org.hibernate.id.CompositeNestedGeneratedValueGenerator;
import org.hibernate.id.OptimizableGenerator;
import org.hibernate.id.PostInsertIdentifierGenerator;
import org.hibernate.id.enhanced.Optimizer;
import org.hibernate.internal.FilterHelper;
import org.hibernate.internal.util.collections.CollectionHelper;
@ -383,6 +382,7 @@ import org.hibernate.sql.results.graph.FetchableContainer;
import org.hibernate.sql.results.graph.instantiation.internal.DynamicInstantiation;
import org.hibernate.sql.results.internal.SqlSelectionImpl;
import org.hibernate.sql.results.internal.StandardEntityGraphTraversalStateImpl;
import org.hibernate.tuple.Generator;
import org.hibernate.tuple.InMemoryGenerator;
import org.hibernate.type.BasicType;
import org.hibernate.type.CustomType;
@ -1230,7 +1230,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
BasicEntityIdentifierMapping identifierMapping = null;
// We use the id property name to null the identifier generator variable if the target paths contain the id
final String identifierPropertyName;
InMemoryGenerator identifierGenerator = entityDescriptor.getGenerator();
Generator identifierGenerator = entityDescriptor.getGenerator();
identifierPropertyName = identifierGenerator != null ? entityDescriptor.getIdentifierPropertyName() : null;
final String versionAttributeName;
boolean needsVersionInsert;
@ -1287,7 +1287,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
}
// This uses identity generation, so we don't need to list the column
if ( identifierGenerator instanceof PostInsertIdentifierGenerator
if ( identifierGenerator != null && identifierGenerator.generatedByDatabase()
|| identifierGenerator instanceof CompositeNestedGeneratedValueGenerator ) {
identifierGenerator = null;
}
@ -1346,7 +1346,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
public static class AdditionalInsertValues {
private final Expression versionExpression;
private final Expression discriminatorExpression;
private final InMemoryGenerator identifierGenerator;
private final Generator identifierGenerator;
private final BasicEntityIdentifierMapping identifierMapping;
private Expression identifierGeneratorParameter;
private SqlSelection versionSelection;
@ -1356,7 +1356,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
public AdditionalInsertValues(
Expression versionExpression,
Expression discriminatorExpression,
InMemoryGenerator identifierGenerator,
Generator identifierGenerator,
BasicEntityIdentifierMapping identifierMapping) {
this.versionExpression = versionExpression;
this.discriminatorExpression = discriminatorExpression;
@ -1372,9 +1372,10 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
if ( discriminatorExpression != null ) {
expressions.add( discriminatorExpression );
}
if ( identifierGenerator != null ) {
if ( identifierGenerator != null && !identifierGenerator.generatedByDatabase() ) {
if ( identifierGeneratorParameter == null ) {
identifierGeneratorParameter = new IdGeneratorParameter( identifierMapping, identifierGenerator );
identifierGeneratorParameter =
new IdGeneratorParameter( identifierMapping, (InMemoryGenerator) identifierGenerator );
}
expressions.add( identifierGeneratorParameter );
}

View File

@ -30,7 +30,7 @@ public class GeneratedAlwaysValueGeneration
}
@Override
public boolean referenceColumnsInSql() {
public boolean referenceColumnsInSql(Dialect dialect) {
return false;
}

View File

@ -46,7 +46,7 @@ public class GeneratedValueGeneration implements InDatabaseGenerator {
}
@Override
public boolean referenceColumnsInSql() {
public boolean referenceColumnsInSql(Dialect dialect) {
return writable;
}

View File

@ -19,7 +19,7 @@ public interface IdentifierAttribute extends Attribute {
@Deprecated
IdentifierGenerator getIdentifierGenerator();
InMemoryGenerator getGenerator();
Generator getGenerator();
boolean isIdentifierAssignedByInsert();

View File

@ -20,7 +20,7 @@ public class IdentifierProperty extends AbstractAttribute implements IdentifierA
private final boolean virtual;
private final boolean embedded;
private final InMemoryGenerator identifierGenerator;
private final Generator identifierGenerator;
private final boolean identifierAssignedByInsert;
private final boolean hasIdentifierMapper;
@ -38,13 +38,13 @@ public class IdentifierProperty extends AbstractAttribute implements IdentifierA
String name,
Type type,
boolean embedded,
InMemoryGenerator identifierGenerator) {
Generator identifierGenerator) {
super( name, type );
this.virtual = false;
this.embedded = embedded;
this.hasIdentifierMapper = false;
this.identifierGenerator = identifierGenerator;
this.identifierAssignedByInsert = identifierGenerator instanceof PostInsertIdentifierGenerator;
this.identifierAssignedByInsert = identifierGenerator.generatedByDatabase();
}
/**
@ -59,13 +59,13 @@ public class IdentifierProperty extends AbstractAttribute implements IdentifierA
Type type,
boolean embedded,
boolean hasIdentifierMapper,
InMemoryGenerator identifierGenerator) {
Generator identifierGenerator) {
super( null, type );
this.virtual = true;
this.embedded = embedded;
this.hasIdentifierMapper = hasIdentifierMapper;
this.identifierGenerator = identifierGenerator;
this.identifierAssignedByInsert = identifierGenerator instanceof PostInsertIdentifierGenerator;
this.identifierAssignedByInsert = identifierGenerator.generatedByDatabase();
}
@Override
@ -84,7 +84,7 @@ public class IdentifierProperty extends AbstractAttribute implements IdentifierA
}
@Override
public InMemoryGenerator getGenerator() {
public Generator getGenerator() {
return identifierGenerator;
}

View File

@ -15,7 +15,7 @@ import org.hibernate.dialect.Dialect;
* statement. In this case, the generated value is retrieved from the database using a SQL
* {@code select}.
* <p>
* Implementations should override {@link #referenceColumnsInSql()},
* Implementations should override {@link #referenceColumnsInSql(Dialect)},
* {@link #writePropertyValue()}, and {@link #getReferencedColumnValues(Dialect)} as needed
* in order to achieve the desired behavior.
*
@ -39,7 +39,7 @@ public interface InDatabaseGenerator extends Generator {
*
* @return {@code true} if the column is included in the column list of the SQL statement.
*/
boolean referenceColumnsInSql();
boolean referenceColumnsInSql(Dialect dialect);
/**
* Determines if the property values are written to JDBC as the argument of a JDBC {@code ?}
@ -49,8 +49,8 @@ public interface InDatabaseGenerator extends Generator {
/**
* A SQL expression indicating how to calculate the generated values when the mapped columns
* are {@linkplain #referenceColumnsInSql() included in the SQL statement}. The SQL expressions
* might be:
* are {@linkplain #referenceColumnsInSql(Dialect) included in the SQL statement}. The SQL
* expressions might be:
* <ul>
* <li>function calls like {@code current_timestamp} or {@code nextval('mysequence')}, or
* <li>syntactic markers like {@code default}.

View File

@ -43,7 +43,7 @@ public final class PropertyFactory {
*/
public static IdentifierProperty buildIdentifierAttribute(
PersistentClass mappedEntity,
InMemoryGenerator generator) {
Generator generator) {
Type type = mappedEntity.getIdentifier().getType();
Property property = mappedEntity.getIdentifierProperty();

View File

@ -100,7 +100,7 @@ public interface ValueGeneration extends InMemoryGenerator, InDatabaseGenerator
}
@Override
default boolean referenceColumnsInSql() {
default boolean referenceColumnsInSql(Dialect dialect) {
return referenceColumnInSql();
}
@ -131,6 +131,6 @@ public interface ValueGeneration extends InMemoryGenerator, InDatabaseGenerator
default boolean writePropertyValue() {
return !generatedByDatabase() // value generated in memory and then written as normal
// current value of property of entity instance written completely as normal
|| referenceColumnsInSql() && getDatabaseGeneratedReferencedColumnValue()==null;
|| referenceColumnInSql() && getDatabaseGeneratedReferencedColumnValue()==null;
}
}

View File

@ -643,7 +643,7 @@ public class EntityMetamodel implements Serializable {
case ALWAYS:
timing = GenerationTiming.ALWAYS;
}
if ( subStrategy.referenceColumnsInSql() ) {
if ( subStrategy.referenceColumnsInSql(dialect) ) {
// override base-line value
referenceColumns = true;
}
@ -703,7 +703,7 @@ public class EntityMetamodel implements Serializable {
}
@Override
public boolean referenceColumnsInSql() {
public boolean referenceColumnsInSql(Dialect dialect) {
return referenceColumnInSql;
}

View File

@ -24,7 +24,6 @@ import org.hibernate.dialect.H2Dialect;
import org.hibernate.dialect.MySQLDialect;
import org.hibernate.exception.ConstraintViolationException;
import org.hibernate.id.BulkInsertionCapableIdentifierGenerator;
import org.hibernate.id.IdentifierGenerator;
import org.hibernate.metamodel.CollectionClassification;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.query.Query;
@ -34,6 +33,7 @@ import org.hibernate.testing.RequiresDialectFeature;
import org.hibernate.testing.SkipForDialect;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.hibernate.tuple.Generator;
import org.junit.Test;
import org.junit.jupiter.api.Assumptions;
import junit.framework.AssertionFailedError;
@ -580,10 +580,9 @@ public class BulkManipulationTest extends BaseCoreFunctionalTestCase {
EntityPersister persister = sessionFactory()
.getMappingMetamodel()
.getEntityDescriptor(entityClass.getName());
IdentifierGenerator generator = persister.getIdentifierGenerator();
return BulkInsertionCapableIdentifierGenerator.class.isInstance( generator )
&& BulkInsertionCapableIdentifierGenerator.class.cast( generator )
.supportsBulkInsertionIdentifierGeneration();
Generator generator = persister.getGenerator();
return generator instanceof BulkInsertionCapableIdentifierGenerator
&& ( (BulkInsertionCapableIdentifierGenerator) generator ).supportsBulkInsertionIdentifierGeneration();
}
@Test