From 82c68d93e93228fd18108de64209881d67ecebdd Mon Sep 17 00:00:00 2001 From: Gavin Date: Wed, 30 Nov 2022 10:02:48 +0100 Subject: [PATCH] HHH-15789 make IdentifierGenerator into a sort of value generator --- .../annotations/SourceGeneration.java | 4 +- ...ompositeNestedGeneratedValueGenerator.java | 3 - .../org/hibernate/id/IdentifierGenerator.java | 59 ++++++++++----- .../id/PersistentIdentifierGenerator.java | 8 +-- .../mapping/GeneratedValueResolver.java | 4 +- .../InDatabaseGeneratedValueResolver.java | 2 +- .../InMemoryGeneratedValueResolver.java | 11 ++- .../internal/GeneratedValuesProcessor.java | 2 +- .../internal/NoGeneratedValueResolver.java | 2 +- .../entity/mutation/InsertCoordinator.java | 3 +- .../mutation/UpdateCoordinatorStandard.java | 6 +- .../InMemoryValueGenerationStrategy.java | 14 ++-- .../hibernate/tuple/TenantIdGeneration.java | 18 ++--- .../org/hibernate/tuple/ValueGeneration.java | 15 ++++ .../tuple/ValueGenerationStrategy.java | 3 +- .../org/hibernate/tuple/ValueGenerator.java | 2 +- .../hibernate/tuple/VmValueGeneration.java | 21 +++--- .../tuple/entity/EntityMetamodel.java | 72 ++++++------------- .../temporals/GeneratedUuidTests.java | 15 ++-- 19 files changed, 126 insertions(+), 138 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/annotations/SourceGeneration.java b/hibernate-core/src/main/java/org/hibernate/annotations/SourceGeneration.java index 47b375ca98..f923ae7151 100644 --- a/hibernate-core/src/main/java/org/hibernate/annotations/SourceGeneration.java +++ b/hibernate-core/src/main/java/org/hibernate/annotations/SourceGeneration.java @@ -79,8 +79,8 @@ public class SourceGeneration } @Override - public ValueGenerator getValueGenerator() { - return valueGenerator; + public Object generate(SharedSessionContractImplementor session, Object owner, Object currentValue) { + return valueGenerator.generateValue( (Session) session, owner, currentValue ); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/id/CompositeNestedGeneratedValueGenerator.java b/hibernate-core/src/main/java/org/hibernate/id/CompositeNestedGeneratedValueGenerator.java index afc87a994e..0ecefba133 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/CompositeNestedGeneratedValueGenerator.java +++ b/hibernate-core/src/main/java/org/hibernate/id/CompositeNestedGeneratedValueGenerator.java @@ -9,7 +9,6 @@ package org.hibernate.id; import java.io.Serializable; import java.util.ArrayList; import java.util.List; -import java.util.Properties; import org.hibernate.HibernateException; import org.hibernate.boot.model.relational.Database; @@ -17,8 +16,6 @@ import org.hibernate.boot.model.relational.ExportableProducer; import org.hibernate.boot.model.relational.SqlStringGenerationContext; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.id.factory.spi.StandardGenerator; -import org.hibernate.service.ServiceRegistry; -import org.hibernate.type.Type; /** * For composite identifiers, defines a number of "nested" generations that 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 03198d6ffd..f8993fe1f5 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/IdentifierGenerator.java +++ b/hibernate-core/src/main/java/org/hibernate/id/IdentifierGenerator.java @@ -7,7 +7,6 @@ package org.hibernate.id; import java.util.Properties; -import jakarta.persistence.GeneratedValue; import org.hibernate.HibernateException; import org.hibernate.MappingException; @@ -16,19 +15,23 @@ import org.hibernate.boot.model.relational.ExportableProducer; import org.hibernate.boot.model.relational.SqlStringGenerationContext; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.service.ServiceRegistry; +import org.hibernate.tuple.GenerationTiming; +import org.hibernate.tuple.InMemoryValueGenerationStrategy; import org.hibernate.type.Type; +import static org.hibernate.tuple.GenerationTiming.INSERT; + /** * The general contract between a class that generates unique - * identifiers and the {@code Session}. It is not intended that - * this interface ever be exposed to the application. It is - * intended that users implement this interface to provide - * custom identifier generation strategies. + * identifiers and the {@link org.hibernate.Session}. It is not + * intended that this interface ever be exposed to the application. + * It is intended that users implement this interface to + * provide custom identifier generation strategies. *

* Implementors should provide a public default constructor. *

- * Implementations that accept configuration parameters should - * also implement {@code Configurable}. + * Implementations that accept configuration parameters should also + * implement {@link Configurable}. *

* Implementors must be thread-safe * @@ -36,7 +39,7 @@ import org.hibernate.type.Type; * * @see PersistentIdentifierGenerator */ -public interface IdentifierGenerator extends Configurable, ExportableProducer { +public interface IdentifierGenerator extends InMemoryValueGenerationStrategy, ExportableProducer, Configurable { /** * The configuration parameter holding the entity name */ @@ -48,8 +51,11 @@ public interface IdentifierGenerator extends Configurable, ExportableProducer { String JPA_ENTITY_NAME = "jpa_entity_name"; /** - * Used as a key to pass the name used as {@link GeneratedValue#generator()} to the - * {@link IdentifierGenerator} as it is configured. + * The configuration parameter holding the name of this + * identifier generator. + * + * @see org.hibernate.annotations.GenericGenerator#name() + * @see jakarta.persistence.GeneratedValue#generator(). */ String GENERATOR_NAME = "GENERATOR_NAME"; @@ -62,7 +68,8 @@ public interface IdentifierGenerator extends Configurable, ExportableProducer { * Configure this instance, given the value of parameters * specified by the user as {@code <param>} elements. *

- * This method is called just once, following instantiation, and before {@link #registerExportables(Database)}. + * This method is called just once, following instantiation, + * and before {@link #registerExportables(Database)}. * * @param type The id property type descriptor * @param params param values, keyed by parameter name @@ -70,13 +77,15 @@ public interface IdentifierGenerator extends Configurable, ExportableProducer { * @throws MappingException If configuration fails. */ @Override - default void configure(Type type, Properties params, ServiceRegistry serviceRegistry) throws MappingException { + default void configure(Type type, Properties params, ServiceRegistry serviceRegistry) { } /** - * Register database objects used by this identifier generator, e.g. sequences, tables, etc. + * Register database objects used by this identifier generator, + * for example, a sequence or tables. *

- * This method is called just once, after {@link #configure(Type, Properties, ServiceRegistry)}. + * This method is called just once, after + * {@link #configure(Type, Properties, ServiceRegistry)}. * * @param database The database instance */ @@ -85,9 +94,12 @@ public interface IdentifierGenerator extends Configurable, ExportableProducer { } /** - * Initializes this instance, in particular pre-generates SQL as necessary. + * Initializes this instance, in particular pre-generates + * SQL as necessary. *

- * This method is called after {@link #registerExportables(Database)}, before first use. + * This method is called after + * {@link #registerExportables(Database)}, + * and before first use. * * @param context A context to help generate SQL strings */ @@ -104,13 +116,26 @@ public interface IdentifierGenerator extends Configurable, ExportableProducer { * * @throws HibernateException Indicates trouble generating the identifier */ - Object generate(SharedSessionContractImplementor session, Object object) throws HibernateException; + Object generate(SharedSessionContractImplementor session, Object object); + + @Override + default Object generate(SharedSessionContractImplementor session, Object owner, Object currentValue) { + return generate( session, owner ); + } + + @Override + default GenerationTiming getGenerationTiming() { + return INSERT; + } /** * Check if JDBC batch inserts are supported. * * @return JDBC batch inserts are supported. + * + * @deprecated this method is no longer called */ + @Deprecated(since="6.2") default boolean supportsJdbcBatchInserts() { return true; } diff --git a/hibernate-core/src/main/java/org/hibernate/id/PersistentIdentifierGenerator.java b/hibernate-core/src/main/java/org/hibernate/id/PersistentIdentifierGenerator.java index 442d9acd97..efb410bf44 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/PersistentIdentifierGenerator.java +++ b/hibernate-core/src/main/java/org/hibernate/id/PersistentIdentifierGenerator.java @@ -8,16 +8,14 @@ package org.hibernate.id; import java.util.Properties; -import org.hibernate.HibernateException; -import org.hibernate.dialect.Dialect; import org.hibernate.service.ServiceRegistry; import org.hibernate.type.Type; /** - * An {@code IdentifierGenerator} that requires creation of database objects. + * An {@link IdentifierGenerator} that requires creation of database objects. *

- * All {@code PersistentIdentifierGenerator}s have access to a special mapping parameter - * in their {@link #configure(Type, Properties, ServiceRegistry)} method: schema + * All instances have access to a special mapping parameter in their + * {@link #configure(Type, Properties, ServiceRegistry)} method: schema * * @author Gavin King * @author Steve Ebersole diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/GeneratedValueResolver.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/GeneratedValueResolver.java index 9892e25946..31920c4ab3 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/GeneratedValueResolver.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/GeneratedValueResolver.java @@ -40,10 +40,10 @@ public interface GeneratedValueResolver { } else { InMemoryValueGenerationStrategy generation = (InMemoryValueGenerationStrategy) valueGeneration; - return new InMemoryGeneratedValueResolver( generation.getValueGenerator(), requestedTiming ); + return new InMemoryGeneratedValueResolver( generation, requestedTiming ); } } GenerationTiming getGenerationTiming(); - Object resolveGeneratedValue(Object[] row, Object entity, SharedSessionContractImplementor session); + Object resolveGeneratedValue(Object[] row, Object entity, SharedSessionContractImplementor session, Object currentValue); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/InDatabaseGeneratedValueResolver.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/InDatabaseGeneratedValueResolver.java index 5d77013105..e31ff2361e 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/InDatabaseGeneratedValueResolver.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/InDatabaseGeneratedValueResolver.java @@ -32,7 +32,7 @@ public class InDatabaseGeneratedValueResolver implements GeneratedValueResolver } @Override - public Object resolveGeneratedValue(Object[] row, Object entity, SharedSessionContractImplementor session) { + public Object resolveGeneratedValue(Object[] row, Object entity, SharedSessionContractImplementor session, Object currentValue) { return row[resultPosition]; } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/InMemoryGeneratedValueResolver.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/InMemoryGeneratedValueResolver.java index 82579f1d19..c8b5efd81b 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/InMemoryGeneratedValueResolver.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/InMemoryGeneratedValueResolver.java @@ -7,10 +7,9 @@ package org.hibernate.metamodel.mapping; import org.hibernate.Internal; -import org.hibernate.Session; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.tuple.GenerationTiming; -import org.hibernate.tuple.ValueGenerator; +import org.hibernate.tuple.InMemoryValueGenerationStrategy; /** * GeneratedValueResolver impl for in-memory generation @@ -20,9 +19,9 @@ import org.hibernate.tuple.ValueGenerator; @Internal public class InMemoryGeneratedValueResolver implements GeneratedValueResolver { private final GenerationTiming generationTiming; - private final ValueGenerator valueGenerator; + private final InMemoryValueGenerationStrategy valueGenerator; - public InMemoryGeneratedValueResolver(ValueGenerator valueGenerator, GenerationTiming generationTiming) { + public InMemoryGeneratedValueResolver(InMemoryValueGenerationStrategy valueGenerator, GenerationTiming generationTiming) { this.valueGenerator = valueGenerator; this.generationTiming = generationTiming; } @@ -33,7 +32,7 @@ public class InMemoryGeneratedValueResolver implements GeneratedValueResolver { } @Override - public Object resolveGeneratedValue(Object[] row, Object entity, SharedSessionContractImplementor session) { - return valueGenerator.generateValue( (Session) session, entity ); + public Object resolveGeneratedValue(Object[] row, Object entity, SharedSessionContractImplementor session, Object currentValue) { + return valueGenerator.generate( session, entity, currentValue ); } } 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 1d7a93c0dc..d6ea4d3fd2 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 @@ -175,7 +175,7 @@ public class GeneratedValuesProcessor { for ( int i = 0; i < valueDescriptors.size(); i++ ) { final GeneratedValueDescriptor descriptor = valueDescriptors.get( i ); - final Object generatedValue = descriptor.resolver.resolveGeneratedValue( dbSelectionResults, entity, session ); + final Object generatedValue = descriptor.resolver.resolveGeneratedValue( dbSelectionResults, entity, session, state[i] ); state[ descriptor.attribute.getStateArrayPosition() ] = generatedValue; descriptor.attribute.getAttributeMetadataAccess() .resolveAttributeMetadata( entityDescriptor ) diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/NoGeneratedValueResolver.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/NoGeneratedValueResolver.java index 3bb5d4ad9d..6cd1232c26 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/NoGeneratedValueResolver.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/NoGeneratedValueResolver.java @@ -26,7 +26,7 @@ public class NoGeneratedValueResolver implements GeneratedValueResolver { } @Override - public Object resolveGeneratedValue(Object[] row, Object entity, SharedSessionContractImplementor session) { + public Object resolveGeneratedValue(Object[] row, Object entity, SharedSessionContractImplementor session, Object currentValue) { throw new UnsupportedMappingException( "NoGeneratedValueResolver does not support generated values" ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/InsertCoordinator.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/InsertCoordinator.java index 6cb50d4ccd..614193fd03 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/InsertCoordinator.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/InsertCoordinator.java @@ -10,7 +10,6 @@ import java.util.ArrayList; import java.util.List; import org.hibernate.Internal; -import org.hibernate.Session; import org.hibernate.engine.jdbc.batch.internal.BasicBatchKey; import org.hibernate.engine.jdbc.mutation.JdbcValueBindings; import org.hibernate.engine.jdbc.mutation.MutationExecutor; @@ -104,7 +103,7 @@ public class InsertCoordinator extends AbstractMutationCoordinator { final InMemoryValueGenerationStrategy[] strategies = entityMetamodel.getInMemoryValueGenerationStrategies(); for ( int i = 0; i < strategies.length; i++ ) { if ( strategies[i] != null && strategies[i].getGenerationTiming().includesInsert() ) { - values[i] = strategies[i].getValueGenerator().generateValue( (Session) session, entity, values[i] ); + values[i] = strategies[i].generate( session, entity, values[i] ); entityPersister().setPropertyValue( entity, i, values[i] ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/UpdateCoordinatorStandard.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/UpdateCoordinatorStandard.java index ded890f254..50a4a6fabf 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/UpdateCoordinatorStandard.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/UpdateCoordinatorStandard.java @@ -14,7 +14,6 @@ import java.util.Set; import org.hibernate.HibernateException; import org.hibernate.Internal; -import org.hibernate.Session; import org.hibernate.engine.OptimisticLockStyle; import org.hibernate.engine.jdbc.batch.internal.BasicBatchKey; import org.hibernate.engine.jdbc.batch.spi.BatchKey; @@ -427,10 +426,7 @@ public class UpdateCoordinatorStandard extends AbstractMutationCoordinator imple for ( int i = 0; i < valueGenerationStrategies.length; i++ ) { if ( valueGenerationStrategies[i] != null && valueGenerationStrategies[i].getGenerationTiming().includesUpdate() ) { - newValues[i] = valueGenerationStrategies[i].getValueGenerator().generateValue( - (Session) session, - object - ); + newValues[i] = valueGenerationStrategies[i].generate( session, object, newValues[i] ); entityPersister().setPropertyValue( object, i, newValues[i] ); fieldsPreUpdateNeeded[count++] = i; } diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/InMemoryValueGenerationStrategy.java b/hibernate-core/src/main/java/org/hibernate/tuple/InMemoryValueGenerationStrategy.java index 3c65b5d494..473a7f1aaa 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/InMemoryValueGenerationStrategy.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/InMemoryValueGenerationStrategy.java @@ -6,6 +6,8 @@ */ package org.hibernate.tuple; +import org.hibernate.engine.spi.SharedSessionContractImplementor; + /** * Java value generation is the responsibility of an associated {@link ValueGenerator}. * In this case, the generated value is written to the database just like any other field @@ -16,14 +18,16 @@ package org.hibernate.tuple; * @since 6.2 */ public interface InMemoryValueGenerationStrategy extends ValueGenerationStrategy { - /** - * Obtain the {@linkplain ValueGenerator Java value generator}, if the value is generated in - * Java, or return {@code null} if the value is generated by the database. + * Generate a value. * - * @return The value generator + * @param session The session from which the request originates. + * @param owner The instance of the object owning the attribute for which we are generating a value. + * @param currentValue The current value assigned to the property, or {@code null} + * + * @return The generated value */ - ValueGenerator getValueGenerator(); + Object generate(SharedSessionContractImplementor session, Object owner, Object currentValue); default boolean generatedByDatabase() { return false; diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/TenantIdGeneration.java b/hibernate-core/src/main/java/org/hibernate/tuple/TenantIdGeneration.java index 219d2eb727..f34beb3c10 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/TenantIdGeneration.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/TenantIdGeneration.java @@ -8,10 +8,10 @@ package org.hibernate.tuple; import org.hibernate.MappingException; import org.hibernate.PropertyValueException; -import org.hibernate.Session; import org.hibernate.annotations.TenantId; import org.hibernate.context.spi.CurrentTenantIdentifierResolver; import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.type.descriptor.java.JavaType; /** @@ -20,7 +20,7 @@ import org.hibernate.type.descriptor.java.JavaType; * @author Gavin King */ public class TenantIdGeneration - implements AnnotationValueGenerationStrategy, InMemoryValueGenerationStrategy, ValueGenerator { + implements AnnotationValueGenerationStrategy, InMemoryValueGenerationStrategy { private String entityName; private String propertyName; @@ -39,13 +39,8 @@ public class TenantIdGeneration } @Override - public ValueGenerator getValueGenerator() { - return this; - } - - @Override - public Object generateValue(Session session, Object owner, Object currentValue) { - SessionFactoryImplementor sessionFactory = (SessionFactoryImplementor) session.getSessionFactory(); + public Object generate(SharedSessionContractImplementor session, Object owner, Object currentValue) { + SessionFactoryImplementor sessionFactory = session.getSessionFactory(); JavaType descriptor = sessionFactory.getTypeConfiguration().getJavaTypeRegistry() .findDescriptor(propertyType); if ( descriptor==null ) { @@ -70,9 +65,4 @@ public class TenantIdGeneration } return tenantId == null ? null : descriptor.fromString(tenantId); //convert to the model type } - - @Override - public Object generateValue(Session session, Object owner) { - throw new UnsupportedOperationException(); - } } diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/ValueGeneration.java b/hibernate-core/src/main/java/org/hibernate/tuple/ValueGeneration.java index c23f7eda88..209f70b6c2 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/ValueGeneration.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/ValueGeneration.java @@ -6,7 +6,9 @@ */ package org.hibernate.tuple; +import org.hibernate.Session; import org.hibernate.dialect.Dialect; +import org.hibernate.engine.spi.SharedSessionContractImplementor; /** * A value generator that can adapt to both Java value generation and database value @@ -16,6 +18,19 @@ import org.hibernate.dialect.Dialect; * @author Gavin King */ public interface ValueGeneration extends InMemoryValueGenerationStrategy, InDatabaseValueGenerationStrategy { + /** + * Obtain the {@linkplain ValueGenerator Java value generator}, if the value is generated in + * Java, or return {@code null} if the value is generated by the database. + * + * @return The value generator + */ + ValueGenerator getValueGenerator(); + + @Override + default Object generate(SharedSessionContractImplementor session, Object owner, Object currentValue) { + return getValueGenerator().generateValue( (Session) session, owner, currentValue ); + } + /** * Determines if the column whose value is generated is included in the column list of the * SQL {@code insert} or {@code update} statement, in the case where the value is generated diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/ValueGenerationStrategy.java b/hibernate-core/src/main/java/org/hibernate/tuple/ValueGenerationStrategy.java index 0cce5b7dd8..35c2f009ab 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/ValueGenerationStrategy.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/ValueGenerationStrategy.java @@ -52,8 +52,9 @@ public interface ValueGenerationStrategy extends Serializable { /** * Determines if the property value is generated in Java, or by the database. + * * @return {@code true} if the value is generated by the database, or false if it is - * generated in Java using a {@link ValueGenerator}. + * generated in Java using a {@link ValueGenerator}. */ boolean generatedByDatabase(); } diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/ValueGenerator.java b/hibernate-core/src/main/java/org/hibernate/tuple/ValueGenerator.java index ea4a66acfe..25ff6f3b78 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/ValueGenerator.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/ValueGenerator.java @@ -34,6 +34,6 @@ public interface ValueGenerator { * @return The generated value */ default T generateValue(Session session, Object owner, Object currentValue) { - return generateValue(session, owner); + return generateValue( session, owner ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/VmValueGeneration.java b/hibernate-core/src/main/java/org/hibernate/tuple/VmValueGeneration.java index 527f9d5bbe..4c633559eb 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/VmValueGeneration.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/VmValueGeneration.java @@ -9,7 +9,9 @@ package org.hibernate.tuple; import java.lang.reflect.Constructor; import org.hibernate.HibernateException; +import org.hibernate.Session; import org.hibernate.annotations.GeneratorType; +import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.internal.util.ReflectHelper; /** @@ -21,11 +23,17 @@ public class VmValueGeneration implements AnnotationValueGenerationStrategy, InMemoryValueGenerationStrategy { private GenerationTiming generationTiming; - private Constructor> constructor; + ValueGenerator generator; @Override public void initialize(GeneratorType annotation, Class propertyType, String entityName, String propertyName) { - constructor = ReflectHelper.getDefaultConstructor( annotation.type() ); + Constructor> constructor = ReflectHelper.getDefaultConstructor(annotation.type()); + try { + generator = constructor.newInstance(); + } + catch (Exception e) { + throw new HibernateException( "Couldn't instantiate value generator", e ); + } generationTiming = annotation.when().getEquivalent(); } @@ -35,12 +43,7 @@ public class VmValueGeneration } @Override - public ValueGenerator getValueGenerator() { - try { - return constructor.newInstance(); - } - catch (Exception e) { - throw new HibernateException( "Couldn't instantiate value generator", e ); - } + public Object generate(SharedSessionContractImplementor session, Object owner, Object currentValue) { + return generator.generateValue( (Session) session, owner, currentValue ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityMetamodel.java b/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityMetamodel.java index 573b80ca98..4fe8fc2dee 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityMetamodel.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityMetamodel.java @@ -29,6 +29,7 @@ import org.hibernate.engine.spi.CascadeStyle; import org.hibernate.engine.spi.CascadeStyles; import org.hibernate.engine.spi.CascadingActions; import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.util.ReflectHelper; import org.hibernate.internal.util.collections.ArrayHelper; @@ -47,7 +48,6 @@ import org.hibernate.tuple.IdentifierProperty; import org.hibernate.tuple.InMemoryValueGenerationStrategy; import org.hibernate.tuple.NonIdentifierAttribute; import org.hibernate.tuple.PropertyFactory; -import org.hibernate.tuple.ValueGenerator; import org.hibernate.type.AssociationType; import org.hibernate.type.CollectionType; import org.hibernate.type.ComponentType; @@ -304,28 +304,25 @@ public class EntityMetamodel implements Serializable { inMemoryValueGenerationStrategies[i] = pair.getInMemoryStrategy(); inDatabaseValueGenerationStrategies[i] = pair.getInDatabaseStrategy(); - if ( pair.getInMemoryStrategy() != null ) { + if ( pair.getInMemoryStrategy() != null + && !pair.getInMemoryStrategy().generatedByDatabase() ) { final GenerationTiming timing = pair.getInMemoryStrategy().getGenerationTiming(); - if ( timing != GenerationTiming.NEVER ) { - final ValueGenerator generator = pair.getInMemoryStrategy().getValueGenerator(); - if ( generator != null ) { - // we have some level of generation indicated - switch ( timing ) { - case INSERT: - foundPreInsertGeneratedValues = true; - break; - case UPDATE: - foundPreUpdateGeneratedValues = true; - break; - case ALWAYS: - foundPreInsertGeneratedValues = true; - foundPreUpdateGeneratedValues = true; - break; - } - } + // we have some level of generation indicated + switch ( timing ) { + case INSERT: + foundPreInsertGeneratedValues = true; + break; + case UPDATE: + foundPreUpdateGeneratedValues = true; + break; + case ALWAYS: + foundPreInsertGeneratedValues = true; + foundPreUpdateGeneratedValues = true; + break; } } - if ( pair.getInDatabaseStrategy() != null ) { + if ( pair.getInDatabaseStrategy() != null + && pair.getInDatabaseStrategy().generatedByDatabase() ) { switch ( pair.getInDatabaseStrategy().getGenerationTiming() ) { case INSERT: foundPostInsertGeneratedValues = true; @@ -463,9 +460,7 @@ public class EntityMetamodel implements Serializable { // the property is generated in full. build the generation strategy pair. if ( !valueGeneration.generatedByDatabase() ) { // in-memory generation - return new GenerationStrategyPair( - FullInMemoryValueGenerationStrategy.create( (InMemoryValueGenerationStrategy) valueGeneration ) - ); + return new GenerationStrategyPair( (InMemoryValueGenerationStrategy) valueGeneration ); } else { // in-db generation @@ -503,7 +498,7 @@ public class EntityMetamodel implements Serializable { this( NoInMemoryValueGenerationStrategy.INSTANCE, NoInDatabaseValueGenerationStrategy.INSTANCE ); } - public GenerationStrategyPair(FullInMemoryValueGenerationStrategy inMemoryStrategy) { + public GenerationStrategyPair(InMemoryValueGenerationStrategy inMemoryStrategy) { this( inMemoryStrategy, NoInDatabaseValueGenerationStrategy.INSTANCE ); } @@ -685,38 +680,11 @@ public class EntityMetamodel implements Serializable { } @Override - public ValueGenerator getValueGenerator() { + public Object generate(SharedSessionContractImplementor session, Object owner, Object currentValue) { return null; } } - private static class FullInMemoryValueGenerationStrategy implements InMemoryValueGenerationStrategy { - private final GenerationTiming timing; - private final ValueGenerator generator; - - private FullInMemoryValueGenerationStrategy(GenerationTiming timing, ValueGenerator generator) { - this.timing = timing; - this.generator = generator; - } - - public static FullInMemoryValueGenerationStrategy create(InMemoryValueGenerationStrategy valueGeneration) { - return new FullInMemoryValueGenerationStrategy( - valueGeneration.getGenerationTiming(), - valueGeneration.getValueGenerator() - ); - } - - @Override - public GenerationTiming getGenerationTiming() { - return timing; - } - - @Override - public ValueGenerator getValueGenerator() { - return generator; - } - } - private static class NoInDatabaseValueGenerationStrategy implements InDatabaseValueGenerationStrategy { /** * Singleton access diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/generated/temporals/GeneratedUuidTests.java b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/generated/temporals/GeneratedUuidTests.java index 7aa70768f5..d654d30060 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/generated/temporals/GeneratedUuidTests.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/generated/temporals/GeneratedUuidTests.java @@ -19,10 +19,10 @@ import jakarta.persistence.Table; import org.hibernate.Session; import org.hibernate.annotations.ValueGenerationType; +import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.tuple.AnnotationValueGenerationStrategy; import org.hibernate.tuple.GenerationTiming; import org.hibernate.tuple.InMemoryValueGenerationStrategy; -import org.hibernate.tuple.ValueGenerator; import org.hibernate.testing.orm.junit.DomainModel; import org.hibernate.testing.orm.junit.SessionFactory; @@ -66,9 +66,7 @@ public class GeneratedUuidTests { assertThat( merged ).isNotNull(); // lastly, make sure we can load it.. - final GeneratedUuidEntity loaded = scope.fromTransaction( (session) -> { - return session.get( GeneratedUuidEntity.class, 1 ); - } ); + final GeneratedUuidEntity loaded = scope.fromTransaction( (session) -> session.get( GeneratedUuidEntity.class, 1 )); assertThat( loaded ).isNotNull(); @@ -88,7 +86,7 @@ public class GeneratedUuidTests { //tag::mapping-generated-custom-ex3[] public static class UuidValueGeneration - implements AnnotationValueGenerationStrategy, InMemoryValueGenerationStrategy, ValueGenerator { + implements AnnotationValueGenerationStrategy, InMemoryValueGenerationStrategy { private GenerationTiming timing; @Override @@ -102,12 +100,7 @@ public class GeneratedUuidTests { } @Override - public ValueGenerator getValueGenerator() { - return this; - } - - @Override - public UUID generateValue(Session session, Object owner) { + public Object generate(SharedSessionContractImplementor session, Object owner, Object currentValue) { return UUID.randomUUID(); } }