remove nexus between Generators and InsertGeneratedIdentifierDelegates

this is certain a very debatable move, but I think it's necessary to
keep the layering intact - we don't want this very technical construct
hanging off the side of the Generator APIs, which are user-visible
This commit is contained in:
Gavin 2022-12-02 03:05:04 +01:00 committed by Gavin King
parent 6a630e3515
commit 7b0ca427dd
14 changed files with 202 additions and 215 deletions

View File

@ -1,41 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.id;
import org.hibernate.boot.model.relational.SqlStringGenerationContext;
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.
*
* @author Gavin King
*/
public abstract class AbstractPostInsertGenerator
implements PostInsertIdentifierGenerator, BulkInsertionCapableIdentifierGenerator {
@Override
public String determineBulkInsertionIdentifierGenerationSelectFragment(SqlStringGenerationContext context) {
return null;
}
@Override
public boolean referenceColumnsInSql(Dialect dialect) {
return dialect.getIdentityColumnSupport().hasIdentityInsertKeyword();
}
@Override
public String[] getReferencedColumnValues(Dialect dialect) {
return new String[] { dialect.getIdentityColumnSupport().getIdentityInsertString() };
}
@Override
public void configure(Type type, Properties params, ServiceRegistry serviceRegistry) {}
}

View File

@ -33,5 +33,7 @@ public interface BulkInsertionCapableIdentifierGenerator extends Generator {
*
* @return The identifier value generation fragment (SQL). {@code null} indicates that no fragment is needed.
*/
String determineBulkInsertionIdentifierGenerationSelectFragment(SqlStringGenerationContext context);
default String determineBulkInsertionIdentifierGenerationSelectFragment(SqlStringGenerationContext context) {
return null;
}
}

View File

@ -6,40 +6,20 @@
*/
package org.hibernate.id;
import org.hibernate.HibernateException;
import org.hibernate.dialect.Dialect;
import org.hibernate.id.insert.BasicSelectingDelegate;
import org.hibernate.id.insert.InsertGeneratedIdentifierDelegate;
import org.hibernate.id.insert.InsertReturningDelegate;
import org.hibernate.persister.entity.EntityPersister;
/**
* A generator for use with ANSI-SQL IDENTITY columns used as the primary key.
* The IdentityGenerator for autoincrement/identity key generation.
* <p>
* Indicates to the {@code Session} that identity (ie. identity/autoincrement
* Indicates to the {@code Session} that identity (i.e. identity/autoincrement
* column) key generation should be used.
*
* @implNote Most of the functionality of this generator is delegated to
* {@link InsertGeneratedIdentifierDelegate} (see
* {@link #getInsertGeneratedIdentifierDelegate}).
* {@link InsertGeneratedIdentifierDelegate}.
*
* @author Christoph Sturm
*/
public class IdentityGenerator extends AbstractPostInsertGenerator {
@Override
public InsertGeneratedIdentifierDelegate getInsertGeneratedIdentifierDelegate(
PostInsertIdentityPersister persister,
Dialect dialect,
boolean useGetGeneratedKeys) throws HibernateException {
if ( useGetGeneratedKeys ) {
return dialect.getIdentityColumnSupport().buildGetGeneratedKeysDelegate( persister, dialect );
}
else if ( dialect.getIdentityColumnSupport().supportsInsertSelectIdentity() ) {
return new InsertReturningDelegate( persister, dialect );
}
else {
return new BasicSelectingDelegate( persister, dialect );
}
}
public class IdentityGenerator implements PostInsertIdentifierGenerator, BulkInsertionCapableIdentifierGenerator {
}

View File

@ -6,11 +6,13 @@
*/
package org.hibernate.id;
import org.hibernate.HibernateException;
import org.hibernate.dialect.Dialect;
import org.hibernate.id.insert.InsertGeneratedIdentifierDelegate;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.tuple.GenerationTiming;
import org.hibernate.tuple.InDatabaseGenerator;
import org.hibernate.type.Type;
import java.util.Properties;
import static org.hibernate.tuple.GenerationTiming.INSERT;
@ -18,10 +20,6 @@ import static org.hibernate.tuple.GenerationTiming.INSERT;
* @author Gavin King
*/
public interface PostInsertIdentifierGenerator extends InDatabaseGenerator, Configurable {
InsertGeneratedIdentifierDelegate getInsertGeneratedIdentifierDelegate(
PostInsertIdentityPersister persister,
Dialect dialect,
boolean isGetGeneratedKeysEnabled) throws HibernateException;
@Override
default GenerationTiming getGenerationTiming() {
@ -32,4 +30,18 @@ public interface PostInsertIdentifierGenerator extends InDatabaseGenerator, Conf
default boolean writePropertyValue() {
return false;
}
@Override
default boolean referenceColumnsInSql(Dialect dialect) {
return dialect.getIdentityColumnSupport().hasIdentityInsertKeyword();
}
@Override
default String[] getReferencedColumnValues(Dialect dialect) {
return new String[] { dialect.getIdentityColumnSupport().getIdentityInsertString() };
}
@Override
default void configure(Type type, Properties params, ServiceRegistry serviceRegistry) {}
}

View File

@ -6,58 +6,39 @@
*/
package org.hibernate.id;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;
import org.hibernate.HibernateException;
import org.hibernate.Internal;
import org.hibernate.MappingException;
import org.hibernate.boot.model.relational.SqlStringGenerationContext;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.id.insert.AbstractSelectingDelegate;
import org.hibernate.id.insert.IdentifierGeneratingInsert;
import org.hibernate.id.insert.InsertGeneratedIdentifierDelegate;
import org.hibernate.jdbc.Expectation;
import org.hibernate.metamodel.mapping.BasicEntityIdentifierMapping;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.sql.model.ast.builder.TableInsertBuilder;
import org.hibernate.sql.model.ast.builder.TableInsertBuilderStandard;
import org.hibernate.type.BasicType;
import org.hibernate.type.Type;
/**
* A generator that selects the just inserted row to determine the identifier
* value assigned by the database. The correct row is located using a unique
* key.
* <p>
* One mapping parameter is required: key (unless a natural-id is defined in the mapping).
* A generator that {@code select}s the just-inserted row to determine the identifier
* value assigned by the database. The correct row is located using a unique key of
* the entity, either:
* <ul>
* <li>the mapped {@linkplain org.hibernate.annotations.NaturalId} of the entity, or
* <li>a property specified using the parameter named {@code "key"}.
* </ul>
* The second approach is provided for backward compatibility with older versions of
* Hibernate.
*
* @see org.hibernate.annotations.NaturalId
*
* @author Gavin King
*/
public class SelectGenerator extends AbstractPostInsertGenerator {
public class SelectGenerator implements PostInsertIdentifierGenerator, BulkInsertionCapableIdentifierGenerator {
private String uniqueKeyPropertyName;
@Override
public void configure(Type type, Properties parameters, ServiceRegistry serviceRegistry) throws MappingException {
public void configure(Type type, Properties parameters, ServiceRegistry serviceRegistry) {
uniqueKeyPropertyName = parameters.getProperty( "key" );
}
@Override
public InsertGeneratedIdentifierDelegate getInsertGeneratedIdentifierDelegate(
PostInsertIdentityPersister persister,
Dialect dialect,
boolean isGetGeneratedKeysEnabled) throws HibernateException {
return new SelectGeneratorDelegate( persister, dialect, uniqueKeyPropertyName );
}
@Internal
public static String determineNameOfPropertyToUse(PostInsertIdentityPersister persister, String supplied) {
if ( supplied != null ) {
return supplied;
public String getUniqueKeyPropertyName(EntityPersister persister) {
if ( uniqueKeyPropertyName != null ) {
return uniqueKeyPropertyName;
}
int[] naturalIdPropertyIndices = persister.getNaturalIdentifierProperties();
if ( naturalIdPropertyIndices == null ) {
@ -80,61 +61,4 @@ public class SelectGenerator extends AbstractPostInsertGenerator {
}
return persister.getPropertyNames()[naturalIdPropertyIndices[0]];
}
private static class SelectGeneratorDelegate extends AbstractSelectingDelegate {
private final PostInsertIdentityPersister persister;
private final Dialect dialect;
private final String uniqueKeyPropertyName;
private final Type uniqueKeyType;
private final BasicType<?> idType;
private final String idSelectString;
public SelectGeneratorDelegate(PostInsertIdentityPersister persister, Dialect dialect, String propertyName) {
super( persister );
this.persister = persister;
this.dialect = dialect;
this.uniqueKeyPropertyName = determineNameOfPropertyToUse( persister, propertyName );
idSelectString = persister.getSelectByUniqueKeyString(this.uniqueKeyPropertyName);
uniqueKeyType = persister.getPropertyType(this.uniqueKeyPropertyName);
idType = (BasicType<?>) persister.getIdentifierType();
}
protected String getSelectSQL() {
return idSelectString;
}
@Override
public IdentifierGeneratingInsert prepareIdentifierGeneratingInsert(SqlStringGenerationContext context) {
return new IdentifierGeneratingInsert( dialect );
}
@Override
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 {
Object uniqueKeyValue = persister.getPropertyValue( entity, uniqueKeyPropertyName );
uniqueKeyType.nullSafeSet( ps, uniqueKeyValue, 1, session );
}
@Override
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 );
}
return idType.getJdbcValueExtractor().extract( rs, 1, session );
}
}
}

View File

@ -547,7 +547,8 @@ public class SequenceStyleGenerator
@Override
public String determineBulkInsertionIdentifierGenerationSelectFragment(SqlStringGenerationContext context) {
return context.getDialect().getSequenceSupport().getSelectSequenceNextValString( context.format( getDatabaseStructure().getPhysicalName() ) );
return context.getDialect().getSequenceSupport()
.getSelectSequenceNextValString( context.format( getDatabaseStructure().getPhysicalName() ) );
}
/**

View File

@ -57,8 +57,7 @@ public abstract class AbstractSelectingDelegate implements InsertGeneratedIdenti
@Override
public PreparedStatement prepareStatement(String insertSql, SharedSessionContractImplementor session) {
final MutationStatementPreparer statementPreparer = session.getJdbcCoordinator().getMutationStatementPreparer();
return statementPreparer.prepareStatement( insertSql, NO_GENERATED_KEYS );
return session.getJdbcCoordinator().getMutationStatementPreparer().prepareStatement( insertSql, NO_GENERATED_KEYS );
}
@Override
@ -73,8 +72,7 @@ public abstract class AbstractSelectingDelegate implements InsertGeneratedIdenti
jdbcServices.getSqlStatementLogger().logStatement( insertStatementDetails.getSqlString() );
jdbcValueBindings.beforeStatement( insertStatementDetails, session );
final PreparedStatement insertStatement = insertStatementDetails.resolveStatement();
jdbcCoordinator.getResultSetReturn().executeUpdate( insertStatement );
jdbcCoordinator.getResultSetReturn().executeUpdate( insertStatementDetails.resolveStatement() );
// the insert is complete, select the generated id...
@ -109,21 +107,19 @@ public abstract class AbstractSelectingDelegate implements InsertGeneratedIdenti
}
@Override
public final Object performInsert(
String insertSQL,
SharedSessionContractImplementor session,
Binder binder) {
StatementPreparer statementPreparer = session.getJdbcCoordinator().getStatementPreparer();
public final Object performInsert(String insertSQL, SharedSessionContractImplementor session, Binder binder) {
JdbcCoordinator jdbcCoordinator = session.getJdbcCoordinator();
StatementPreparer statementPreparer = jdbcCoordinator.getStatementPreparer();
try {
// prepare and execute the insert
PreparedStatement insert = statementPreparer.prepareStatement( insertSQL, NO_GENERATED_KEYS );
try {
binder.bindValues( insert );
session.getJdbcCoordinator().getResultSetReturn().executeUpdate( insert );
jdbcCoordinator.getResultSetReturn().executeUpdate( insert );
}
finally {
session.getJdbcCoordinator().getLogicalConnection().getResourceRegistry().release( insert );
session.getJdbcCoordinator().afterStatementExecution();
jdbcCoordinator.getLogicalConnection().getResourceRegistry().release( insert );
jdbcCoordinator.afterStatementExecution();
}
}
catch (SQLException sqle) {
@ -141,17 +137,17 @@ public abstract class AbstractSelectingDelegate implements InsertGeneratedIdenti
PreparedStatement idSelect = statementPreparer.prepareStatement( selectSQL, false );
try {
bindParameters( binder.getEntity(), idSelect, session );
ResultSet rs = session.getJdbcCoordinator().getResultSetReturn().extract( idSelect );
ResultSet rs = jdbcCoordinator.getResultSetReturn().extract( idSelect );
try {
return extractGeneratedValue( binder.getEntity(), rs, session );
}
finally {
session.getJdbcCoordinator().getLogicalConnection().getResourceRegistry().release( rs, idSelect );
jdbcCoordinator.getLogicalConnection().getResourceRegistry().release( rs, idSelect );
}
}
finally {
session.getJdbcCoordinator().getLogicalConnection().getResourceRegistry().release( idSelect );
session.getJdbcCoordinator().afterStatementExecution();
jdbcCoordinator.getLogicalConnection().getResourceRegistry().release( idSelect );
jdbcCoordinator.afterStatementExecution();
}
}
@ -159,7 +155,7 @@ public abstract class AbstractSelectingDelegate implements InsertGeneratedIdenti
throw session.getJdbcServices().getSqlExceptionHelper().convert(
sqle,
"could not retrieve generated id after insert: " + MessageHelper.infoString( persister ),
insertSQL
selectSQL
);
}
}

View File

@ -11,6 +11,7 @@ import java.sql.SQLException;
import org.hibernate.boot.model.relational.SqlStringGenerationContext;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.identity.IdentityColumnSupport;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.id.IdentifierGeneratorHelper;
@ -20,6 +21,8 @@ import org.hibernate.metamodel.mapping.BasicEntityIdentifierMapping;
import org.hibernate.sql.model.ast.builder.TableInsertBuilder;
import org.hibernate.sql.model.ast.builder.TableInsertBuilderStandard;
import static org.hibernate.id.IdentifierGeneratorHelper.getGeneratedIdentity;
/**
* Delegate for dealing with IDENTITY columns where the dialect requires an
* additional command execution to retrieve the generated IDENTITY value
@ -37,7 +40,7 @@ public class BasicSelectingDelegate extends AbstractSelectingDelegate {
@Override
public IdentifierGeneratingInsert prepareIdentifierGeneratingInsert(SqlStringGenerationContext context) {
IdentifierGeneratingInsert insert = new IdentifierGeneratingInsert( dialect );
insert.addIdentityColumn( persister.getRootTableKeyColumnNames()[ 0 ] );
insert.addIdentityColumn( persister.getRootTableKeyColumnNames()[0] );
return insert;
}
@ -45,16 +48,17 @@ public class BasicSelectingDelegate extends AbstractSelectingDelegate {
public TableInsertBuilder createTableInsertBuilder(
BasicEntityIdentifierMapping identifierMapping,
Expectation expectation,
SessionFactoryImplementor sessionFactory) {
final TableInsertBuilder builder = new TableInsertBuilderStandard(
persister,
persister.getIdentifierTableMapping(),
sessionFactory
);
SessionFactoryImplementor factory) {
final TableInsertBuilder builder =
new TableInsertBuilderStandard( persister, persister.getIdentifierTableMapping(), factory );
final String value = dialect.getIdentityColumnSupport().getIdentityInsertString();
if ( value != null ) {
builder.addKeyColumn( identifierMapping.getSelectionExpression(), value, identifierMapping.getJdbcMapping() );
IdentityColumnSupport identityColumnSupport = dialect.getIdentityColumnSupport();
if ( identityColumnSupport.hasIdentityInsertKeyword() ) {
builder.addKeyColumn(
identifierMapping.getSelectionExpression(),
identityColumnSupport.getIdentityInsertString(),
identifierMapping.getJdbcMapping()
);
}
return builder;
@ -68,10 +72,10 @@ public class BasicSelectingDelegate extends AbstractSelectingDelegate {
@Override
protected Object extractGeneratedValue(Object entity, ResultSet rs, SharedSessionContractImplementor session)
throws SQLException {
return IdentifierGeneratorHelper.getGeneratedIdentity(
return getGeneratedIdentity(
rs,
persister.getNavigableRole(),
persister.getRootTableKeyColumnNames()[ 0 ],
persister.getRootTableKeyColumnNames()[0],
persister.getIdentifierType(),
session.getJdbcServices().getJdbcEnvironment().getDialect()
);

View File

@ -48,11 +48,6 @@ public interface InsertGeneratedIdentifierDelegate {
Object entity,
SharedSessionContractImplementor session);
/**
* Build a {@link org.hibernate.sql.Insert} specific to the delegate's mode
* of handling generated key values.

View File

@ -0,0 +1,79 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.id.insert;
import org.hibernate.boot.model.relational.SqlStringGenerationContext;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.id.IdentifierGenerationException;
import org.hibernate.id.PostInsertIdentityPersister;
import org.hibernate.jdbc.Expectation;
import org.hibernate.metamodel.mapping.BasicEntityIdentifierMapping;
import org.hibernate.sql.model.ast.builder.TableInsertBuilder;
import org.hibernate.sql.model.ast.builder.TableInsertBuilderStandard;
import org.hibernate.type.BasicType;
import org.hibernate.type.Type;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class SelectGeneratorDelegate extends AbstractSelectingDelegate {
private final PostInsertIdentityPersister persister;
private final Dialect dialect;
private final String uniqueKeyPropertyName;
private final Type uniqueKeyType;
private final BasicType<?> idType;
private final String idSelectString;
public SelectGeneratorDelegate(PostInsertIdentityPersister persister, Dialect dialect, String uniqueKeyPropertyName) {
super( persister );
this.persister = persister;
this.dialect = dialect;
this.uniqueKeyPropertyName = uniqueKeyPropertyName;
idSelectString = persister.getSelectByUniqueKeyString(this.uniqueKeyPropertyName);
uniqueKeyType = persister.getPropertyType(this.uniqueKeyPropertyName);
idType = (BasicType<?>) persister.getIdentifierType();
}
protected String getSelectSQL() {
return idSelectString;
}
@Override
public IdentifierGeneratingInsert prepareIdentifierGeneratingInsert(SqlStringGenerationContext context) {
return new IdentifierGeneratingInsert( dialect );
}
@Override
public TableInsertBuilder createTableInsertBuilder(
BasicEntityIdentifierMapping identifierMapping,
Expectation expectation,
SessionFactoryImplementor factory) {
return new TableInsertBuilderStandard( persister, persister.getIdentifierTableMapping(), factory );
}
protected void bindParameters(Object entity, PreparedStatement ps, SharedSessionContractImplementor session)
throws SQLException {
uniqueKeyType.nullSafeSet( ps, persister.getPropertyValue( entity, uniqueKeyPropertyName ), 1, session );
}
@Override
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);
}
return idType.getJdbcValueExtractor().extract( rs, 1, session );
}
}

View File

@ -99,8 +99,11 @@ import org.hibernate.id.IdentifierGenerator;
import org.hibernate.id.OptimizableGenerator;
import org.hibernate.id.PostInsertIdentifierGenerator;
import org.hibernate.id.PostInsertIdentityPersister;
import org.hibernate.id.insert.SelectGeneratorDelegate;
import org.hibernate.id.enhanced.Optimizer;
import org.hibernate.id.insert.BasicSelectingDelegate;
import org.hibernate.id.insert.InsertGeneratedIdentifierDelegate;
import org.hibernate.id.insert.InsertReturningDelegate;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.FilterAliasGenerator;
@ -259,7 +262,6 @@ import org.hibernate.stat.spi.StatisticsImplementor;
import org.hibernate.tuple.Generator;
import org.hibernate.tuple.InDatabaseGenerator;
import org.hibernate.tuple.GenerationTiming;
import org.hibernate.tuple.InMemoryGenerator;
import org.hibernate.tuple.NonIdentifierAttribute;
import org.hibernate.tuple.entity.EntityBasedAssociationAttribute;
import org.hibernate.tuple.entity.EntityMetamodel;
@ -2868,6 +2870,25 @@ public abstract class AbstractEntityPersister
return getFactory().getSessionFactoryOptions().isGetGeneratedKeysEnabled();
}
public InsertGeneratedIdentifierDelegate getGeneratedIdentifierDelegate() {
Dialect dialect = getFactory().getJdbcServices().getDialect();
if ( useGetGeneratedKeys() ) {
return dialect.getIdentityColumnSupport().buildGetGeneratedKeysDelegate(this, dialect );
}
else if ( dialect.getIdentityColumnSupport().supportsInsertSelectIdentity() ) {
return new InsertReturningDelegate(this, dialect );
}
else {
return new BasicSelectingDelegate(this, dialect );
}
}
@Override
public InsertGeneratedIdentifierDelegate getGeneratedIdentifierDelegateForProperty(String uniqueKeyPropertyName) {
Dialect dialect = getFactory().getJdbcServices().getDialect();
return new SelectGeneratorDelegate( this, dialect, uniqueKeyPropertyName );
}
@Override
public String getIdentitySelectString() {
//TODO: cache this in an instvar
@ -3179,12 +3200,11 @@ public abstract class AbstractEntityPersister
private void doLateInit() {
if ( isIdentifierAssignedByInsert() ) {
final PostInsertIdentifierGenerator idGenerator = (PostInsertIdentifierGenerator) getGenerator();
identityDelegate = idGenerator.getInsertGeneratedIdentifierDelegate(
this,
getFactory().getJdbcServices().getDialect(),
useGetGeneratedKeys()
);
final InDatabaseGenerator generator = (InDatabaseGenerator) getGenerator();
final String uniqueKeyPropertyName = generator.getUniqueKeyPropertyName(this);
identityDelegate = uniqueKeyPropertyName == null
? getGeneratedIdentifierDelegate()
: getGeneratedIdentifierDelegateForProperty( uniqueKeyPropertyName );
}
tableMappings = buildTableMappings();

View File

@ -28,6 +28,7 @@ import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.event.spi.EventSource;
import org.hibernate.id.IdentifierGenerator;
import org.hibernate.id.insert.InsertGeneratedIdentifierDelegate;
import org.hibernate.internal.FilterAliasGenerator;
import org.hibernate.internal.TableGroupFilterAliasGenerator;
import org.hibernate.loader.ast.spi.Loadable;
@ -1002,6 +1003,14 @@ public interface EntityPersister
boolean canUseReferenceCacheEntries();
default InsertGeneratedIdentifierDelegate getGeneratedIdentifierDelegate() {
return null;
}
default InsertGeneratedIdentifierDelegate getGeneratedIdentifierDelegateForProperty(String uniqueKeyPropertyName) {
return null;
}
/**
* The property name of the "special" identifier property in HQL
*

View File

@ -36,6 +36,7 @@ import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.MappingModelExpressible;
import org.hibernate.metamodel.mapping.ModelPartContainer;
import org.hibernate.persister.entity.AbstractEntityPersister;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.query.SemanticException;
import org.hibernate.query.results.TableGroupImpl;
import org.hibernate.query.spi.DomainQueryExecutionContext;
@ -74,6 +75,7 @@ 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.InDatabaseGenerator;
import org.hibernate.tuple.InMemoryGenerator;
import org.hibernate.type.descriptor.ValueBinder;
@ -302,7 +304,8 @@ public class InsertExecutionDelegate implements TableBasedInsertHandler.Executio
true
);
final Generator generator = entityDescriptor.getEntityPersister().getGenerator();
final EntityPersister entityPersister = entityDescriptor.getEntityPersister();
final Generator generator = entityPersister.getGenerator();
final List<Assignment> assignments = assignmentsByTable.get( updatingTableReference );
if ( ( assignments == null || assignments.isEmpty() )
&& !generator.generatedByDatabase()
@ -556,13 +559,11 @@ public class InsertExecutionDelegate implements TableBasedInsertHandler.Executio
.translate( null, executionContext.getQueryOptions() );
if ( generator.generatedByDatabase() ) {
final PostInsertIdentifierGenerator postInsertGenerator = (PostInsertIdentifierGenerator) generator;
final boolean generatedKeysEnabled = sessionFactory.getSessionFactoryOptions().isGetGeneratedKeysEnabled();
final InsertGeneratedIdentifierDelegate identifierDelegate = postInsertGenerator.getInsertGeneratedIdentifierDelegate(
(PostInsertIdentityPersister) entityDescriptor.getEntityPersister(),
jdbcServices.getDialect(),
generatedKeysEnabled
);
final InDatabaseGenerator databaseGenerator = (InDatabaseGenerator) generator;
final String uniqueKeyPropertyName = databaseGenerator.getUniqueKeyPropertyName( entityPersister );
final InsertGeneratedIdentifierDelegate identifierDelegate = uniqueKeyPropertyName == null
? entityPersister.getGeneratedIdentifierDelegate()
: entityPersister.getGeneratedIdentifierDelegateForProperty( uniqueKeyPropertyName );
final String finalSql = identifierDelegate.prepareIdentifierGeneratingInsert( jdbcInsert.getSqlString() );
final BasicEntityIdentifierMapping identifierMapping = (BasicEntityIdentifierMapping) entityDescriptor.getIdentifierMapping();
final ValueBinder jdbcValueBinder = identifierMapping.getJdbcMapping().getJdbcValueBinder();

View File

@ -7,6 +7,7 @@
package org.hibernate.tuple;
import org.hibernate.dialect.Dialect;
import org.hibernate.persister.entity.EntityPersister;
/**
* A value generated by the database might be generated implicitly, by a trigger, or using
@ -62,6 +63,10 @@ public interface InDatabaseGenerator extends Generator {
*/
String[] getReferencedColumnValues(Dialect dialect);
default String getUniqueKeyPropertyName(EntityPersister persister) {
return null;
}
default boolean generatedByDatabase() {
return true;
}