make PostInsertIdentifierGenerator extend InDatabaseGenerator
This commit is contained in:
parent
4b2f8ff8ae
commit
6a630e3515
|
@ -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
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -42,5 +42,4 @@ public class IdentityGenerator extends AbstractPostInsertGenerator {
|
|||
return new BasicSelectingDelegate( persister, dialect );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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() );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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() );
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
|
|
@ -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 ) {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ public class GeneratedAlwaysValueGeneration
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean referenceColumnsInSql() {
|
||||
public boolean referenceColumnsInSql(Dialect dialect) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ public class GeneratedValueGeneration implements InDatabaseGenerator {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean referenceColumnsInSql() {
|
||||
public boolean referenceColumnsInSql(Dialect dialect) {
|
||||
return writable;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ public interface IdentifierAttribute extends Attribute {
|
|||
@Deprecated
|
||||
IdentifierGenerator getIdentifierGenerator();
|
||||
|
||||
InMemoryGenerator getGenerator();
|
||||
Generator getGenerator();
|
||||
|
||||
boolean isIdentifierAssignedByInsert();
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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}.
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue