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:
parent
6a630e3515
commit
7b0ca427dd
|
@ -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) {}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
}
|
||||
|
|
|
@ -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) {}
|
||||
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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() ) );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue