diff --git a/hibernate-core/src/main/java/org/hibernate/id/IdentifierGenerator.java b/hibernate-core/src/main/java/org/hibernate/id/IdentifierGenerator.java index d25d52bb84..98ca5dfeaf 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/IdentifierGenerator.java +++ b/hibernate-core/src/main/java/org/hibernate/id/IdentifierGenerator.java @@ -23,8 +23,9 @@ import static org.hibernate.tuple.GenerationTiming.INSERT; /** * A classic extension point from the very earliest days of Hibernate, - * this interface is now no longer the only way to generate identifiers. - * Any {@link InMemoryGenerator} may now be used. + * this interface is no longer the only way to generate identifiers. Any + * {@link InMemoryGenerator} with timing {@link GenerationTiming#INSERT} + * may now be used. *
* This interface extends {@code InMemoryGenerator} with some additional * machinery for {@linkplain #configure configuration}, and for caching @@ -54,6 +55,7 @@ import static org.hibernate.tuple.GenerationTiming.INSERT; * * @author Gavin King * + * @see PostInsertIdentifierGenerator * @see PersistentIdentifierGenerator */ public interface IdentifierGenerator extends InMemoryGenerator, ExportableProducer, Configurable { @@ -94,8 +96,7 @@ public interface IdentifierGenerator extends InMemoryGenerator, ExportableProduc * @throws MappingException If configuration fails. */ @Override - default void configure(Type type, Properties parameters, ServiceRegistry serviceRegistry) { - } + default void configure(Type type, Properties parameters, ServiceRegistry serviceRegistry) {} /** * Register database objects used by this identifier generator, @@ -107,8 +108,7 @@ public interface IdentifierGenerator extends InMemoryGenerator, ExportableProduc * @param database The database instance */ @Override - default void registerExportables(Database database) { - } + default void registerExportables(Database database) {} /** * Initializes this instance, in particular pre-generates @@ -120,8 +120,7 @@ public interface IdentifierGenerator extends InMemoryGenerator, ExportableProduc * * @param context A context to help generate SQL strings */ - default void initialize(SqlStringGenerationContext context) { - } + default void initialize(SqlStringGenerationContext context) {} /** * Generate a new identifier. @@ -135,11 +134,19 @@ public interface IdentifierGenerator extends InMemoryGenerator, ExportableProduc */ Object generate(SharedSessionContractImplementor session, Object object); + /** + * Generate a value. + *
+ * The {@code currentValue} is usually null for id generation. + */ @Override default Object generate(SharedSessionContractImplementor session, Object owner, Object currentValue) { return generate( session, owner ); } + /** + * @return {@link GenerationTiming#INSERT} + */ @Override default GenerationTiming getGenerationTiming() { return INSERT; diff --git a/hibernate-core/src/main/java/org/hibernate/id/IdentityGenerator.java b/hibernate-core/src/main/java/org/hibernate/id/IdentityGenerator.java index 8841da8b09..6d1742b7ae 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/IdentityGenerator.java +++ b/hibernate-core/src/main/java/org/hibernate/id/IdentityGenerator.java @@ -6,22 +6,29 @@ */ package org.hibernate.id; +import org.hibernate.dialect.Dialect; import org.hibernate.id.factory.spi.StandardGenerator; -import org.hibernate.id.insert.InsertGeneratedIdentifierDelegate; -import org.hibernate.persister.entity.EntityPersister; +import org.hibernate.tuple.InDatabaseGenerator; /** - * A generator for use with ANSI-SQL IDENTITY columns used as the primary key. - * The IdentityGenerator for autoincrement/identity key generation. + * An {@link InDatabaseGenerator} that handles {@code IDENTITY}/"autoincrement" columns + * on those databases which support them. *
- * 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}. + * Delegates to the {@link org.hibernate.dialect.identity.IdentityColumnSupport} provided + * by the {@linkplain Dialect#getIdentityColumnSupport() dialect}. * * @author Christoph Sturm */ public class IdentityGenerator implements PostInsertIdentifierGenerator, BulkInsertionCapableIdentifierGenerator, StandardGenerator { + @Override + public boolean referenceColumnsInSql(Dialect dialect) { + return dialect.getIdentityColumnSupport().hasIdentityInsertKeyword(); + } + + @Override + public String[] getReferencedColumnValues(Dialect dialect) { + return new String[] { dialect.getIdentityColumnSupport().getIdentityInsertString() }; + } + } diff --git a/hibernate-core/src/main/java/org/hibernate/id/PostInsertIdentifierGenerator.java b/hibernate-core/src/main/java/org/hibernate/id/PostInsertIdentifierGenerator.java index 95a77fcf1c..e7b6165e1d 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/PostInsertIdentifierGenerator.java +++ b/hibernate-core/src/main/java/org/hibernate/id/PostInsertIdentifierGenerator.java @@ -6,7 +6,6 @@ */ package org.hibernate.id; -import org.hibernate.dialect.Dialect; import org.hibernate.service.ServiceRegistry; import org.hibernate.tuple.GenerationTiming; import org.hibernate.tuple.InDatabaseGenerator; @@ -17,31 +16,37 @@ import java.util.Properties; import static org.hibernate.tuple.GenerationTiming.INSERT; /** + * The counterpart of {@link IdentifierGenerator} for values generated by the database. + * This interface is no longer the only way to handle database-generate identifiers. + * Any {@link InDatabaseGenerator} with timing {@link GenerationTiming#INSERT} may now + * be used. + * + * @see IdentifierGenerator + * * @author Gavin King */ public interface PostInsertIdentifierGenerator extends InDatabaseGenerator, Configurable { + /** + * @return {@link GenerationTiming#INSERT} + */ @Override default GenerationTiming getGenerationTiming() { return INSERT; } + /** + * @return {@code false}, since we don't usually have a meaningful property value + * for generated identifiers + */ @Override 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() }; - } - + /** + * Noop default implementation. May be overridden by subtypes. + */ @Override default void configure(Type type, Properties params, ServiceRegistry serviceRegistry) {} - } diff --git a/hibernate-core/src/main/java/org/hibernate/id/SelectGenerator.java b/hibernate-core/src/main/java/org/hibernate/id/SelectGenerator.java index 65ffb3c93b..d3121521aa 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/SelectGenerator.java +++ b/hibernate-core/src/main/java/org/hibernate/id/SelectGenerator.java @@ -8,28 +8,30 @@ package org.hibernate.id; import java.util.Properties; -import org.hibernate.id.factory.spi.StandardGenerator; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.service.ServiceRegistry; import org.hibernate.type.Type; /** - * 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: + * A generator that {@code select}s the just-{@code insert}ed row to determine the + * {@code IDENTITY} column value assigned by the database. The correct row is located + * using a unique key of the entity, either: *
+ * Arguably, this class breaks the natural separation of responsibility between the + * {@linkplain org.hibernate.tuple.InDatabaseGenerator generator} and the coordinating + * code, since it's role is to specify how the generated value is retrieved. * * @see org.hibernate.annotations.NaturalId * * @author Gavin King */ -public class SelectGenerator - implements PostInsertIdentifierGenerator, BulkInsertionCapableIdentifierGenerator, StandardGenerator { +public class SelectGenerator extends IdentityGenerator { private String uniqueKeyPropertyName; @Override diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/GeneratedValuesProcessor.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/GeneratedValuesProcessor.java index dab308a0a9..ca701a5fe0 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/GeneratedValuesProcessor.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/GeneratedValuesProcessor.java @@ -37,7 +37,18 @@ import org.hibernate.sql.results.spi.ListResultsConsumer; import org.hibernate.tuple.GenerationTiming; import org.hibernate.tuple.Generator; +import static org.hibernate.sql.results.spi.ListResultsConsumer.UniqueSemantic.FILTER; + /** + * Responsible for retrieving {@linkplain org.hibernate.tuple.InDatabaseGenerator + * database-generated} attribute values after an {@code insert} statement is executed. + *
+ * Note that this class has responsibility for regular attributes of the entity. The
+ * primary key / id attribute is handled separately, being the responsibility of an
+ * instance of {@link org.hibernate.id.insert.InsertGeneratedIdentifierDelegate}.
+ *
+ * @see org.hibernate.tuple.InDatabaseGenerator
+ *
* @author Steve Ebersole
*/
@Incubating
@@ -56,12 +67,7 @@ public class GeneratedValuesProcessor {
this.entityDescriptor = entityDescriptor;
this.sessionFactory = sessionFactory;
- // NOTE: we only care about db-generated values here. in-memory generation
- // is applied before the insert/update happens.
-
- // todo (6.0): for now, we rely on the entity metamodel as composite attributes report
- // GenerationTiming.NEVER even if they have attributes that would need generation
- final List