kill off some awful code in IdentifierGeneratorHelper

- should make multi-column (post insert) id generators work by side effect
- also make StandardGenerator a mixin type interface
This commit is contained in:
Gavin 2022-12-02 13:35:44 +01:00 committed by Gavin King
parent 4195772c15
commit 337919b766
20 changed files with 104 additions and 254 deletions

View File

@ -19,7 +19,7 @@ import org.hibernate.internal.util.BytesHelper;
* @see UUIDHexGenerator * @see UUIDHexGenerator
* @author Gavin King * @author Gavin King
*/ */
public abstract class AbstractUUIDGenerator implements StandardGenerator { public abstract class AbstractUUIDGenerator implements IdentifierGenerator, StandardGenerator {
private static final int IP; private static final int IP;
static { static {

View File

@ -23,7 +23,7 @@ import org.hibernate.type.Type;
* *
* @author Gavin King * @author Gavin King
*/ */
public class Assigned implements StandardGenerator { public class Assigned implements IdentifierGenerator, StandardGenerator {
private String entityName; private String entityName;
public Object generate(SharedSessionContractImplementor session, Object obj) throws HibernateException { public Object generate(SharedSessionContractImplementor session, Object obj) throws HibernateException {
@ -34,7 +34,6 @@ public class Assigned implements StandardGenerator {
"ids for this class must be manually assigned before calling save(): " + entityName "ids for this class must be manually assigned before calling save(): " + entityName
); );
} }
return id; return id;
} }

View File

@ -48,7 +48,7 @@ import org.hibernate.id.factory.spi.StandardGenerator;
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class CompositeNestedGeneratedValueGenerator public class CompositeNestedGeneratedValueGenerator
implements StandardGenerator, IdentifierGeneratorAggregator, Serializable { implements IdentifierGenerator, StandardGenerator, IdentifierGeneratorAggregator, Serializable {
/** /**
* Contract for declaring how to locate the context for sub-value injection. * Contract for declaring how to locate the context for sub-value injection.
*/ */
@ -91,7 +91,7 @@ public class CompositeNestedGeneratedValueGenerator
} }
private final GenerationContextLocator generationContextLocator; private final GenerationContextLocator generationContextLocator;
private List<GenerationPlan> generationPlans = new ArrayList<>(); private final List<GenerationPlan> generationPlans = new ArrayList<>();
public CompositeNestedGeneratedValueGenerator(GenerationContextLocator generationContextLocator) { public CompositeNestedGeneratedValueGenerator(GenerationContextLocator generationContextLocator) {
this.generationContextLocator = generationContextLocator; this.generationContextLocator = generationContextLocator;
@ -105,9 +105,8 @@ public class CompositeNestedGeneratedValueGenerator
public Object generate(SharedSessionContractImplementor session, Object object) throws HibernateException { public Object generate(SharedSessionContractImplementor session, Object object) throws HibernateException {
final Object context = generationContextLocator.locateGenerationContext( session, object ); final Object context = generationContextLocator.locateGenerationContext( session, object );
for ( Object generationPlan : generationPlans ) { for ( GenerationPlan generationPlan : generationPlans ) {
final GenerationPlan plan = (GenerationPlan) generationPlan; generationPlan.execute( session, object, context );
plan.execute( session, object, context );
} }
return context; return context;

View File

@ -22,7 +22,10 @@ import org.hibernate.service.ServiceRegistry;
import org.hibernate.type.EntityType; import org.hibernate.type.EntityType;
import org.hibernate.type.Type; import org.hibernate.type.Type;
import static org.hibernate.engine.internal.ForeignKeys.getEntityIdentifierIfNotUnsaved;
import static org.hibernate.id.IdentifierGeneratorHelper.SHORT_CIRCUIT_INDICATOR;
import static org.hibernate.internal.CoreLogging.messageLogger; import static org.hibernate.internal.CoreLogging.messageLogger;
import static org.hibernate.loader.PropertyPath.IDENTIFIER_MAPPER_PROPERTY;
/** /**
* <b>foreign</b> * <b>foreign</b>
@ -34,7 +37,7 @@ import static org.hibernate.internal.CoreLogging.messageLogger;
* *
* @author Gavin King * @author Gavin King
*/ */
public class ForeignGenerator implements StandardGenerator { public class ForeignGenerator implements IdentifierGenerator, StandardGenerator {
private static final CoreMessageLogger LOG = messageLogger( ForeignGenerator.class ); private static final CoreMessageLogger LOG = messageLogger( ForeignGenerator.class );
private String entityName; private String entityName;
@ -99,31 +102,27 @@ public class ForeignGenerator implements StandardGenerator {
} }
else { else {
// try identifier mapper // try identifier mapper
foreignValueSourceType = (EntityType) entityDescriptor.getPropertyType( PropertyPath.IDENTIFIER_MAPPER_PROPERTY + "." + propertyName ); foreignValueSourceType = (EntityType)
entityDescriptor.getPropertyType( IDENTIFIER_MAPPER_PROPERTY + "." + propertyName );
} }
Object id; Object id;
String associatedEntityName = foreignValueSourceType.getAssociatedEntityName();
try { try {
id = ForeignKeys.getEntityIdentifierIfNotUnsaved( id = getEntityIdentifierIfNotUnsaved( associatedEntityName, associatedObject, sessionImplementor );
foreignValueSourceType.getAssociatedEntityName(),
associatedObject,
sessionImplementor
);
} }
catch (TransientObjectException toe) { catch (TransientObjectException toe) {
if ( LOG.isDebugEnabled() ) { if ( LOG.isDebugEnabled() ) {
LOG.debugf( LOG.debugf(
"ForeignGenerator detected a transient entity [%s]", "ForeignGenerator detected a transient entity [%s]",
foreignValueSourceType.getAssociatedEntityName() associatedEntityName
); );
} }
if ( sessionImplementor instanceof Session ) { if ( sessionImplementor instanceof Session ) {
id = ((Session) sessionImplementor) id = ((Session) sessionImplementor).save( associatedEntityName, associatedObject );
.save(foreignValueSourceType.getAssociatedEntityName(), associatedObject);
} }
else if ( sessionImplementor instanceof StatelessSession ) { else if ( sessionImplementor instanceof StatelessSession ) {
id = ((StatelessSession) sessionImplementor) id = ((StatelessSession) sessionImplementor).insert( associatedEntityName, associatedObject );
.insert(foreignValueSourceType.getAssociatedEntityName(), associatedObject);
} }
else { else {
throw new IdentifierGenerationException("sessionImplementor is neither Session nor StatelessSession"); throw new IdentifierGenerationException("sessionImplementor is neither Session nor StatelessSession");
@ -132,7 +131,7 @@ public class ForeignGenerator implements StandardGenerator {
if ( sessionImplementor instanceof Session && ((Session) sessionImplementor).contains( entityName, object ) ) { if ( sessionImplementor instanceof Session && ((Session) sessionImplementor).contains( entityName, object ) ) {
//abort the save (the object is already saved by a circular cascade) //abort the save (the object is already saved by a circular cascade)
return IdentifierGeneratorHelper.SHORT_CIRCUIT_INDICATOR; return SHORT_CIRCUIT_INDICATOR;
//throw new IdentifierGenerationException("save associated object first, or disable cascade for inverse association"); //throw new IdentifierGenerationException("save associated object first, or disable cascade for inverse association");
} }
return id; return id;

View File

@ -24,7 +24,7 @@ import org.hibernate.internal.CoreMessageLogger;
* @deprecated use {@link org.hibernate.id.uuid.UuidGenerator} * @deprecated use {@link org.hibernate.id.uuid.UuidGenerator}
*/ */
@Deprecated(since = "6.0") @Deprecated(since = "6.0")
public class GUIDGenerator implements StandardGenerator { public class GUIDGenerator implements IdentifierGenerator, StandardGenerator {
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( GUIDGenerator.class ); private static final CoreMessageLogger LOG = CoreLogging.messageLogger( GUIDGenerator.class );
private static boolean WARNED; private static boolean WARNED;
@ -39,21 +39,20 @@ public class GUIDGenerator implements StandardGenerator {
public Object generate(SharedSessionContractImplementor session, Object obj) throws HibernateException { public Object generate(SharedSessionContractImplementor session, Object obj) throws HibernateException {
final String sql = session.getJdbcServices().getJdbcEnvironment().getDialect().getSelectGUIDString(); final String sql = session.getJdbcServices().getJdbcEnvironment().getDialect().getSelectGUIDString();
try { try {
PreparedStatement st = session.getJdbcCoordinator().getStatementPreparer().prepareStatement( sql ); final PreparedStatement st = session.getJdbcCoordinator().getStatementPreparer().prepareStatement( sql );
try { try {
ResultSet rs = session.getJdbcCoordinator().getResultSetReturn().extract( st ); final ResultSet rs = session.getJdbcCoordinator().getResultSetReturn().extract( st );
final String result;
try { try {
if ( !rs.next() ) { if ( !rs.next() ) {
throw new HibernateException( "The database returned no GUID identity value" ); throw new HibernateException( "The database returned no GUID identity value" );
} }
result = rs.getString( 1 ); final String result = rs.getString( 1 );
LOG.guidGenerated( result );
return result;
} }
finally { finally {
session.getJdbcCoordinator().getLogicalConnection().getResourceRegistry().release( rs, st ); session.getJdbcCoordinator().getLogicalConnection().getResourceRegistry().release( rs, st );
} }
LOG.guidGenerated( result );
return result;
} }
finally { finally {
session.getJdbcCoordinator().getLogicalConnection().getResourceRegistry().release( st ); session.getJdbcCoordinator().getLogicalConnection().getResourceRegistry().release( st );

View File

@ -6,25 +6,26 @@
*/ */
package org.hibernate.id; package org.hibernate.id;
import org.hibernate.HibernateException;
import org.hibernate.dialect.Dialect;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.metamodel.mapping.SqlTypedMapping;
import org.hibernate.metamodel.model.domain.NavigableRole;
import org.hibernate.type.descriptor.WrapperOptions;
import java.io.Serializable; import java.io.Serializable;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.BigInteger; import java.math.BigInteger;
import java.math.RoundingMode; import java.math.RoundingMode;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.Locale;
import java.util.Objects; import java.util.Objects;
import org.hibernate.HibernateException;
import org.hibernate.dialect.Dialect;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.metamodel.model.domain.NavigableRole;
import org.hibernate.type.CustomType;
import org.hibernate.type.Type;
/** /**
* Factory and helper methods for {@link IdentifierGenerator} framework. * Factory and helper methods for {@link IdentifierGenerator} framework.
* *
@ -58,151 +59,53 @@ public final class IdentifierGeneratorHelper {
} }
}; };
/** /**
* Get the generated identifier when using identity columns * Get the generated identifier when using identity columns
* *
* @param resultSet The result set from which to extract the generated identity. * @param path The {@link NavigableRole#getFullPath()}
* @param identityColumn The name of the identifier column * @param resultSet The result set from which to extract the generated identity
* @param type The expected type mapping for the identity value. * @param wrapperOptions The session
* @param dialect The current database dialect.
*
* @return The generated identity value * @return The generated identity value
*
* @throws SQLException Can be thrown while accessing the result set * @throws SQLException Can be thrown while accessing the result set
* @throws HibernateException Indicates a problem reading back a generated identity value. * @throws HibernateException Indicates a problem reading back a generated identity value.
*/ */
public static Object getGeneratedIdentity( public static Object getGeneratedIdentity(
String path,
ResultSet resultSet, ResultSet resultSet,
NavigableRole insertionTargetRole, PostInsertIdentityPersister persister,
String identityColumn, WrapperOptions wrapperOptions) throws SQLException {
Type type,
Dialect dialect) throws SQLException {
if ( !resultSet.next() ) { if ( !resultSet.next() ) {
throw new HibernateException( "The database returned no natively generated identity value : " + insertionTargetRole.getFullPath() ); throw new HibernateException( "The database returned no natively generated identity value : " + path );
} }
final Object id = get( resultSet, insertionTargetRole, identityColumn, type, dialect ); JdbcMapping identifierType = ( (SqlTypedMapping) persister.getIdentifierMapping() ).getJdbcMapping();
LOG.debugf( "Natively generated identity (%s) : %s", insertionTargetRole.getFullPath(), id ); Object id = identifierType.getJdbcValueExtractor()
.extract( resultSet, columnIndex( resultSet, persister ), wrapperOptions );
LOG.debugf( "Natively generated identity (%s) : %s", path, id );
return id; return id;
} }
/** private static int columnIndex(ResultSet resultSet, PostInsertIdentityPersister persister) {
* Extract the value from the result set (which is assumed to already have been positioned to the appropriate row)
* and wrp it in the appropriate Java numeric type.
*
* @param resultSet The result set from which to extract the value.
* @param identifier The name of the identifier column
* @param type The expected type of the value.
* @param dialect The current database dialect.
*
* @return The extracted value.
*
* @throws SQLException Indicates problems access the result set
* @throws IdentifierGenerationException Indicates an unknown type.
*/
public static Object get(
ResultSet resultSet,
NavigableRole insertionTargetRole,
String identifier,
Type type,
Dialect dialect)
throws SQLException, IdentifierGenerationException {
if ( type instanceof ResultSetIdentifierConsumer ) {
return ( (ResultSetIdentifierConsumer) type ).consumeIdentifier( resultSet );
}
if ( type instanceof CustomType ) {
final CustomType<?> customType = (CustomType<?>) type;
if ( customType.getUserType() instanceof ResultSetIdentifierConsumer ) {
return ( (ResultSetIdentifierConsumer) customType.getUserType() ).consumeIdentifier( resultSet );
}
}
int columnCount = getColumnCount( resultSet );
final Class<?> clazz = type.getReturnedClass();
if ( columnCount == 1 ) {
if ( clazz == Long.class ) {
return resultSet.getLong( 1 );
}
else if ( clazz == Integer.class ) {
return resultSet.getInt( 1 );
}
else if ( clazz == Short.class ) {
return resultSet.getShort( 1 );
}
else if ( clazz == String.class ) {
return resultSet.getString( 1 );
}
else if ( clazz == BigInteger.class ) {
return resultSet.getBigDecimal( 1 )
.setScale( 0, RoundingMode.UNNECESSARY )
.toBigInteger();
}
else if ( clazz == BigDecimal.class ) {
return resultSet.getBigDecimal( 1 )
.setScale( 0, RoundingMode.UNNECESSARY );
}
else {
throw new IdentifierGenerationException(
String.format(
Locale.ROOT,
"Unrecognized id type (%s - %s) for extraction - %s",
type.getName(),
clazz.getName(),
insertionTargetRole.getFullPath()
)
);
}
}
else {
try { try {
return extractIdentifier( resultSet, identifier, type, clazz ); ResultSetMetaData metaData = resultSet.getMetaData();
String keyColumnName = persister.getRootTableKeyColumnNames()[0];
Dialect dialect = persister.getFactory().getJdbcServices().getDialect();
for ( int i = 1 ; i<=metaData.getColumnCount(); i++ ) {
if ( equal( keyColumnName, metaData.getColumnName(i), dialect ) ) {
return i;
}
}
} }
catch (SQLException e) { catch (SQLException e) {
if ( StringHelper.isQuoted( identifier, dialect ) ) { LOG.debugf( "Could not determine column index from JDBC metadatda", e );
return extractIdentifier( resultSet, StringHelper.unquote( identifier, dialect ), type, clazz );
} }
throw e;
}
}
}
private static int getColumnCount(ResultSet resultSet) {
try {
return resultSet.getMetaData().getColumnCount();
}
catch (Exception e) {
//Oracle driver will throw NPE
}
return 1; return 1;
} }
private static Object extractIdentifier(ResultSet rs, String identifier, Type type, Class<?> clazz) private static boolean equal(String keyColumnName, String alias, Dialect dialect) {
throws SQLException { return alias.equals( keyColumnName )
if ( clazz == Long.class ) { || StringHelper.isQuoted( keyColumnName, dialect )
return rs.getLong( identifier ); && alias.equals( StringHelper.unquote( keyColumnName, dialect ) );
}
else if ( clazz == Integer.class ) {
return rs.getInt( identifier );
}
else if ( clazz == Short.class ) {
return rs.getShort( identifier );
}
else if ( clazz == String.class ) {
return rs.getString( identifier );
}
else if ( clazz == BigInteger.class ) {
return rs.getBigDecimal( identifier ).setScale( 0, RoundingMode.UNNECESSARY ).toBigInteger();
}
else if ( clazz == BigDecimal.class ) {
return rs.getBigDecimal( identifier ).setScale( 0, RoundingMode.UNNECESSARY );
}
else {
throw new IdentifierGenerationException(
"unrecognized id type : " + type.getName() + " -> " + clazz.getName()
);
}
} }
public static IntegralDataTypeHolder getIntegralDataTypeHolder(Class<?> integralType) { public static IntegralDataTypeHolder getIntegralDataTypeHolder(Class<?> integralType) {
@ -714,8 +617,6 @@ public final class IdentifierGeneratorHelper {
} }
} }
/** /**
* Disallow instantiation of IdentifierGeneratorHelper. * Disallow instantiation of IdentifierGeneratorHelper.
*/ */

View File

@ -6,6 +6,7 @@
*/ */
package org.hibernate.id; package org.hibernate.id;
import org.hibernate.id.factory.spi.StandardGenerator;
import org.hibernate.id.insert.InsertGeneratedIdentifierDelegate; import org.hibernate.id.insert.InsertGeneratedIdentifierDelegate;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
@ -21,5 +22,6 @@ import org.hibernate.persister.entity.EntityPersister;
* *
* @author Christoph Sturm * @author Christoph Sturm
*/ */
public class IdentityGenerator implements PostInsertIdentifierGenerator, BulkInsertionCapableIdentifierGenerator { public class IdentityGenerator
implements PostInsertIdentifierGenerator, BulkInsertionCapableIdentifierGenerator, StandardGenerator {
} }

View File

@ -15,7 +15,6 @@ import java.util.Properties;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.MappingException; import org.hibernate.MappingException;
import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.boot.model.naming.ObjectNameNormalizer; import org.hibernate.boot.model.naming.ObjectNameNormalizer;
import org.hibernate.boot.model.relational.QualifiedTableName; import org.hibernate.boot.model.relational.QualifiedTableName;
import org.hibernate.boot.model.relational.SqlStringGenerationContext; import org.hibernate.boot.model.relational.SqlStringGenerationContext;
@ -44,7 +43,7 @@ import org.hibernate.type.Type;
* @author Steve Ebersole * @author Steve Ebersole
* @author Brett Meyer * @author Brett Meyer
*/ */
public class IncrementGenerator implements StandardGenerator { public class IncrementGenerator implements IdentifierGenerator, StandardGenerator {
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( IncrementGenerator.class ); private static final CoreMessageLogger LOG = CoreLogging.messageLogger( IncrementGenerator.class );
private Class<?> returnClass; private Class<?> returnClass;

View File

@ -14,7 +14,7 @@ import org.hibernate.id.factory.spi.StandardGenerator;
/** /**
* Commonality between sequence-based and table-based generators * Commonality between sequence-based and table-based generators
*/ */
public interface OptimizableGenerator extends StandardGenerator, ExportableProducer { public interface OptimizableGenerator extends IdentifierGenerator, StandardGenerator, ExportableProducer {
/** /**
* If an explicit sequence/table name is not configured, * If an explicit sequence/table name is not configured,
*/ */
@ -42,9 +42,7 @@ public interface OptimizableGenerator extends StandardGenerator, ExportableProdu
/** /**
* Indicates the optimizer to use, either naming a {@link Optimizer} implementation class or naming * Indicates the optimizer to use, either naming a {@link Optimizer} implementation class or naming
* a {@link StandardOptimizerDescriptor} by name * a {@link StandardOptimizerDescriptor} by name. Takes precedence over {@link #INCREMENT_PARAM}.
*
* NOTE : has precedence over {@link #INCREMENT_PARAM}
*/ */
String OPT_PARAM = "optimizer"; String OPT_PARAM = "optimizer";

View File

@ -15,7 +15,10 @@ import java.sql.ResultSet;
* numeric types handled by {@link IdentifierGeneratorHelper} * numeric types handled by {@link IdentifierGeneratorHelper}
* *
* @author Steve Ebersole * @author Steve Ebersole
*
* @deprecated this interface is unnecessary and no longer used
*/ */
@Deprecated(since = "6.2")
public interface ResultSetIdentifierConsumer { public interface ResultSetIdentifierConsumer {
/** /**
* Given a result set, consume/extract the necessary values and construct an * Given a result set, consume/extract the necessary values and construct an

View File

@ -8,6 +8,7 @@ package org.hibernate.id;
import java.util.Properties; import java.util.Properties;
import org.hibernate.id.factory.spi.StandardGenerator;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistry;
import org.hibernate.type.Type; import org.hibernate.type.Type;
@ -27,7 +28,8 @@ import org.hibernate.type.Type;
* *
* @author Gavin King * @author Gavin King
*/ */
public class SelectGenerator implements PostInsertIdentifierGenerator, BulkInsertionCapableIdentifierGenerator { public class SelectGenerator
implements PostInsertIdentifierGenerator, BulkInsertionCapableIdentifierGenerator, StandardGenerator {
private String uniqueKeyPropertyName; private String uniqueKeyPropertyName;
@Override @Override

View File

@ -41,7 +41,7 @@ import org.hibernate.type.descriptor.java.UUIDJavaType;
* {@link org.hibernate.annotations.UuidGenerator} instead * {@link org.hibernate.annotations.UuidGenerator} instead
*/ */
@Deprecated(since = "6.0") @Deprecated(since = "6.0")
public class UUIDGenerator implements StandardGenerator { public class UUIDGenerator implements IdentifierGenerator, StandardGenerator {
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( UUIDGenerator.class ); private static final CoreMessageLogger LOG = CoreLogging.messageLogger( UUIDGenerator.class );
public static final String UUID_GEN_STRATEGY = "uuid_gen_strategy"; public static final String UUID_GEN_STRATEGY = "uuid_gen_strategy";
@ -61,12 +61,12 @@ public class UUIDGenerator implements StandardGenerator {
if ( strategyClassName != null ) { if ( strategyClassName != null ) {
try { try {
final ClassLoaderService cls = serviceRegistry.getService( ClassLoaderService.class ); final ClassLoaderService cls = serviceRegistry.getService( ClassLoaderService.class );
final Class strategyClass = cls.classForName( strategyClassName ); final Class<?> strategyClass = cls.classForName( strategyClassName );
try { try {
strategy = (UUIDGenerationStrategy) strategyClass.newInstance(); strategy = (UUIDGenerationStrategy) strategyClass.newInstance();
} }
catch ( Exception ignore ) { catch ( Exception e ) {
LOG.unableToInstantiateUuidGenerationStrategy(ignore); LOG.unableToInstantiateUuidGenerationStrategy(e);
} }
} }
catch ( ClassLoadingException ignore ) { catch ( ClassLoadingException ignore ) {

View File

@ -6,10 +6,8 @@
*/ */
package org.hibernate.id.factory.spi; package org.hibernate.id.factory.spi;
import org.hibernate.id.IdentifierGenerator;
/** /**
* Marker interface for Hibernate-provided generator impls * Marker interface for Hibernate-provided implementations of {@link org.hibernate.tuple.Generator}.
*/ */
public interface StandardGenerator extends IdentifierGenerator { public interface StandardGenerator {
} }

View File

@ -20,6 +20,7 @@ import org.hibernate.id.PostInsertIdentityPersister;
import org.hibernate.pretty.MessageHelper; import org.hibernate.pretty.MessageHelper;
import static java.sql.Statement.NO_GENERATED_KEYS; import static java.sql.Statement.NO_GENERATED_KEYS;
import static org.hibernate.id.IdentifierGeneratorHelper.getGeneratedIdentity;
/** /**
* Abstract {@link InsertGeneratedIdentifierDelegate} implementation where * Abstract {@link InsertGeneratedIdentifierDelegate} implementation where
@ -47,12 +48,12 @@ public abstract class AbstractSelectingDelegate implements InsertGeneratedIdenti
} }
/** /**
* Extract the generated key value from the given result set * Extract the generated key value from the given result set after execution of {@link #getSelectSQL()}.
* from execution of {@link #getSelectSQL()}.
*
*/ */
protected abstract Object extractGeneratedValue(Object entity, ResultSet rs, SharedSessionContractImplementor session) protected Object extractGeneratedValue(ResultSet resultSet, SharedSessionContractImplementor session)
throws SQLException; throws SQLException {
return getGeneratedIdentity( persister.getNavigableRole().getFullPath(), resultSet, persister, session );
}
@Override @Override
public PreparedStatement prepareStatement(String insertSql, SharedSessionContractImplementor session) { public PreparedStatement prepareStatement(String insertSql, SharedSessionContractImplementor session) {
@ -82,7 +83,7 @@ public abstract class AbstractSelectingDelegate implements InsertGeneratedIdenti
final ResultSet resultSet = session.getJdbcCoordinator().getResultSetReturn().extract( idSelect ); final ResultSet resultSet = session.getJdbcCoordinator().getResultSetReturn().extract( idSelect );
try { try {
return extractGeneratedValue( entity, resultSet, session ); return extractGeneratedValue( resultSet, session );
} }
catch (SQLException e) { catch (SQLException e) {
throw jdbcServices.getSqlExceptionHelper().convert( throw jdbcServices.getSqlExceptionHelper().convert(
@ -136,12 +137,12 @@ public abstract class AbstractSelectingDelegate implements InsertGeneratedIdenti
PreparedStatement idSelect = statementPreparer.prepareStatement( selectSQL, false ); PreparedStatement idSelect = statementPreparer.prepareStatement( selectSQL, false );
try { try {
bindParameters( binder.getEntity(), idSelect, session ); bindParameters( binder.getEntity(), idSelect, session );
ResultSet rs = jdbcCoordinator.getResultSetReturn().extract( idSelect ); ResultSet resultSet = jdbcCoordinator.getResultSetReturn().extract( idSelect );
try { try {
return extractGeneratedValue( binder.getEntity(), rs, session ); return extractGeneratedValue( resultSet, session );
} }
finally { finally {
jdbcCoordinator.getLogicalConnection().getResourceRegistry().release( rs, idSelect ); jdbcCoordinator.getLogicalConnection().getResourceRegistry().release( resultSet, idSelect );
} }
} }
finally { finally {

View File

@ -6,14 +6,10 @@
*/ */
package org.hibernate.id.insert; package org.hibernate.id.insert;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.hibernate.MappingException; import org.hibernate.MappingException;
import org.hibernate.boot.model.relational.SqlStringGenerationContext; import org.hibernate.boot.model.relational.SqlStringGenerationContext;
import org.hibernate.dialect.Dialect; import org.hibernate.dialect.Dialect;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.id.PostInsertIdentityPersister; import org.hibernate.id.PostInsertIdentityPersister;
import org.hibernate.jdbc.Expectation; import org.hibernate.jdbc.Expectation;
import org.hibernate.metamodel.mapping.BasicEntityIdentifierMapping; import org.hibernate.metamodel.mapping.BasicEntityIdentifierMapping;
@ -21,8 +17,6 @@ import org.hibernate.sql.model.ast.builder.TableInsertBuilder;
import org.hibernate.sql.model.ast.builder.TableInsertBuilderStandard; import org.hibernate.sql.model.ast.builder.TableInsertBuilderStandard;
import org.hibernate.tuple.InDatabaseGenerator; import org.hibernate.tuple.InDatabaseGenerator;
import static org.hibernate.id.IdentifierGeneratorHelper.getGeneratedIdentity;
/** /**
* Delegate for dealing with {@code IDENTITY} columns where the dialect requires an * Delegate for dealing with {@code IDENTITY} columns where the dialect requires an
* additional command execution to retrieve the generated {@code IDENTITY} value * additional command execution to retrieve the generated {@code IDENTITY} value
@ -37,7 +31,7 @@ public class BasicSelectingDelegate extends AbstractSelectingDelegate {
this.dialect = dialect; this.dialect = dialect;
} }
@Override @Override @Deprecated
public IdentifierGeneratingInsert prepareIdentifierGeneratingInsert(SqlStringGenerationContext context) { public IdentifierGeneratingInsert prepareIdentifierGeneratingInsert(SqlStringGenerationContext context) {
IdentifierGeneratingInsert insert = new IdentifierGeneratingInsert( dialect ); IdentifierGeneratingInsert insert = new IdentifierGeneratingInsert( dialect );
insert.addGeneratedColumns( persister.getRootTableKeyColumnNames(), (InDatabaseGenerator) persister.getGenerator() ); insert.addGeneratedColumns( persister.getRootTableKeyColumnNames(), (InDatabaseGenerator) persister.getGenerator() );
@ -71,16 +65,4 @@ public class BasicSelectingDelegate extends AbstractSelectingDelegate {
protected String getSelectSQL() { protected String getSelectSQL() {
return persister.getIdentitySelectString(); return persister.getIdentitySelectString();
} }
@Override
protected Object extractGeneratedValue(Object entity, ResultSet resultSet, SharedSessionContractImplementor session)
throws SQLException {
return getGeneratedIdentity(
resultSet,
persister.getNavigableRole(),
DelegateHelper.getKeyColumnName( persister ),
persister.getIdentifierType(),
session.getJdbcServices().getJdbcEnvironment().getDialect()
);
}
} }

View File

@ -46,7 +46,7 @@ public class GetGeneratedKeysDelegate extends AbstractReturningDelegate {
this.dialect = dialect; this.dialect = dialect;
} }
@Override @Override @Deprecated
public IdentifierGeneratingInsert prepareIdentifierGeneratingInsert(SqlStringGenerationContext context) { public IdentifierGeneratingInsert prepareIdentifierGeneratingInsert(SqlStringGenerationContext context) {
IdentifierGeneratingInsert insert = new IdentifierGeneratingInsert( dialect ); IdentifierGeneratingInsert insert = new IdentifierGeneratingInsert( dialect );
insert.addGeneratedColumns( persister.getRootTableKeyColumnNames(), (InDatabaseGenerator) persister.getGenerator() ); insert.addGeneratedColumns( persister.getRootTableKeyColumnNames(), (InDatabaseGenerator) persister.getGenerator() );
@ -104,13 +104,7 @@ public class GetGeneratedKeysDelegate extends AbstractReturningDelegate {
try { try {
final ResultSet resultSet = insertStatement.getGeneratedKeys(); final ResultSet resultSet = insertStatement.getGeneratedKeys();
try { try {
return getGeneratedIdentity( return getGeneratedIdentity( persister.getNavigableRole().getFullPath(), resultSet, persister, session );
resultSet,
persister.getNavigableRole(),
DelegateHelper.getKeyColumnName( persister ),
persister.getIdentifierType(),
jdbcServices.getJdbcEnvironment().getDialect()
);
} }
catch (SQLException e) { catch (SQLException e) {
throw jdbcServices.getSqlExceptionHelper().convert( throw jdbcServices.getSqlExceptionHelper().convert(
@ -158,13 +152,7 @@ public class GetGeneratedKeysDelegate extends AbstractReturningDelegate {
try { try {
final ResultSet resultSet = insertStatement.getGeneratedKeys(); final ResultSet resultSet = insertStatement.getGeneratedKeys();
try { try {
return getGeneratedIdentity( return getGeneratedIdentity( persister.getNavigableRole().getFullPath(), resultSet, persister, session );
resultSet,
persister.getNavigableRole(),
DelegateHelper.getKeyColumnName( persister ),
persister.getIdentifierType(),
jdbcServices.getJdbcEnvironment().getDialect()
);
} }
catch (SQLException e) { catch (SQLException e) {
throw jdbcServices.getSqlExceptionHelper().convert( throw jdbcServices.getSqlExceptionHelper().convert(

View File

@ -54,7 +54,10 @@ public interface InsertGeneratedIdentifierDelegate {
* *
* @param context A context to help generate SQL strings * @param context A context to help generate SQL strings
* @return The insert object. * @return The insert object.
*
* @deprecated this is no longer called
*/ */
@Deprecated(since = "6.2")
IdentifierGeneratingInsert prepareIdentifierGeneratingInsert(SqlStringGenerationContext context); IdentifierGeneratingInsert prepareIdentifierGeneratingInsert(SqlStringGenerationContext context);
/** /**

View File

@ -43,7 +43,7 @@ public class InsertReturningDelegate extends AbstractReturningDelegate {
this.dialect = dialect; this.dialect = dialect;
} }
@Override @Override @Deprecated
public IdentifierGeneratingInsert prepareIdentifierGeneratingInsert(SqlStringGenerationContext context) { public IdentifierGeneratingInsert prepareIdentifierGeneratingInsert(SqlStringGenerationContext context) {
InsertSelectIdentityInsert insert = new InsertSelectIdentityInsert( dialect ); InsertSelectIdentityInsert insert = new InsertSelectIdentityInsert( dialect );
insert.addGeneratedColumns( persister.getRootTableKeyColumnNames(), (InDatabaseGenerator) persister.getGenerator() ); insert.addGeneratedColumns( persister.getRootTableKeyColumnNames(), (InDatabaseGenerator) persister.getGenerator() );
@ -67,15 +67,8 @@ public class InsertReturningDelegate extends AbstractReturningDelegate {
final JdbcServices jdbcServices = session.getJdbcServices(); final JdbcServices jdbcServices = session.getJdbcServices();
final ResultSet resultSet = jdbcCoordinator.getResultSetReturn().execute( insertStatement ); final ResultSet resultSet = jdbcCoordinator.getResultSetReturn().execute( insertStatement );
try { try {
return getGeneratedIdentity( return getGeneratedIdentity( persister.getNavigableRole().getFullPath(), resultSet, persister, session );
resultSet,
persister.getNavigableRole(),
DelegateHelper.getKeyColumnName( persister ),
persister.getIdentifierType(),
jdbcServices.getJdbcEnvironment().getDialect()
);
} }
catch (SQLException e) { catch (SQLException e) {
throw jdbcServices.getSqlExceptionHelper().convert( throw jdbcServices.getSqlExceptionHelper().convert(

View File

@ -10,17 +10,14 @@ import org.hibernate.boot.model.relational.SqlStringGenerationContext;
import org.hibernate.dialect.Dialect; import org.hibernate.dialect.Dialect;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.id.IdentifierGenerationException;
import org.hibernate.id.PostInsertIdentityPersister; import org.hibernate.id.PostInsertIdentityPersister;
import org.hibernate.jdbc.Expectation; import org.hibernate.jdbc.Expectation;
import org.hibernate.metamodel.mapping.BasicEntityIdentifierMapping; import org.hibernate.metamodel.mapping.BasicEntityIdentifierMapping;
import org.hibernate.sql.model.ast.builder.TableInsertBuilder; import org.hibernate.sql.model.ast.builder.TableInsertBuilder;
import org.hibernate.sql.model.ast.builder.TableInsertBuilderStandard; import org.hibernate.sql.model.ast.builder.TableInsertBuilderStandard;
import org.hibernate.type.BasicType;
import org.hibernate.type.Type; import org.hibernate.type.Type;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
/** /**
@ -32,7 +29,6 @@ public class UniqueKeySelectingDelegate extends AbstractSelectingDelegate {
private final String uniqueKeyPropertyName; private final String uniqueKeyPropertyName;
private final Type uniqueKeyType; private final Type uniqueKeyType;
private final BasicType<?> idType;
private final String idSelectString; private final String idSelectString;
@ -45,14 +41,13 @@ public class UniqueKeySelectingDelegate extends AbstractSelectingDelegate {
idSelectString = persister.getSelectByUniqueKeyString( uniqueKeyPropertyName ); idSelectString = persister.getSelectByUniqueKeyString( uniqueKeyPropertyName );
uniqueKeyType = persister.getPropertyType( uniqueKeyPropertyName ); uniqueKeyType = persister.getPropertyType( uniqueKeyPropertyName );
idType = (BasicType<?>) persister.getIdentifierType();
} }
protected String getSelectSQL() { protected String getSelectSQL() {
return idSelectString; return idSelectString;
} }
@Override @Override @Deprecated
public IdentifierGeneratingInsert prepareIdentifierGeneratingInsert(SqlStringGenerationContext context) { public IdentifierGeneratingInsert prepareIdentifierGeneratingInsert(SqlStringGenerationContext context) {
return new IdentifierGeneratingInsert( dialect ); return new IdentifierGeneratingInsert( dialect );
} }
@ -69,14 +64,4 @@ public class UniqueKeySelectingDelegate extends AbstractSelectingDelegate {
throws SQLException { throws SQLException {
uniqueKeyType.nullSafeSet( ps, persister.getPropertyValue( entity, uniqueKeyPropertyName ), 1, session ); uniqueKeyType.nullSafeSet( ps, persister.getPropertyValue( entity, uniqueKeyPropertyName ), 1, session );
} }
@Override
protected Object extractGeneratedValue(Object entity, ResultSet resultSet, SharedSessionContractImplementor session)
throws SQLException {
if ( !resultSet.next() ) {
throw new IdentifierGenerationException("the inserted row could not be located by the unique key: "
+ uniqueKeyPropertyName);
}
return idType.getJdbcValueExtractor().extract( resultSet, 1, session );
}
} }

View File

@ -38,7 +38,6 @@ import org.junit.jupiter.api.Test;
import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.MatcherAssert.assertThat;
@DomainModel( @DomainModel(