HHH-15789 make IdentifierGenerator into a sort of value generator

This commit is contained in:
Gavin 2022-11-30 10:02:48 +01:00 committed by Gavin King
parent 1c083a5863
commit 82c68d93e9
19 changed files with 126 additions and 138 deletions

View File

@ -79,8 +79,8 @@ public class SourceGeneration
} }
@Override @Override
public ValueGenerator<?> getValueGenerator() { public Object generate(SharedSessionContractImplementor session, Object owner, Object currentValue) {
return valueGenerator; return valueGenerator.generateValue( (Session) session, owner, currentValue );
} }
@Override @Override

View File

@ -9,7 +9,6 @@ package org.hibernate.id;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Properties;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.boot.model.relational.Database; 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.boot.model.relational.SqlStringGenerationContext;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.id.factory.spi.StandardGenerator; 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 * For composite identifiers, defines a number of "nested" generations that

View File

@ -7,7 +7,6 @@
package org.hibernate.id; package org.hibernate.id;
import java.util.Properties; import java.util.Properties;
import jakarta.persistence.GeneratedValue;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.MappingException; 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.boot.model.relational.SqlStringGenerationContext;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistry;
import org.hibernate.tuple.GenerationTiming;
import org.hibernate.tuple.InMemoryValueGenerationStrategy;
import org.hibernate.type.Type; import org.hibernate.type.Type;
import static org.hibernate.tuple.GenerationTiming.INSERT;
/** /**
* The general contract between a class that generates unique * The general contract between a class that generates unique
* identifiers and the {@code Session}. It is not intended that * identifiers and the {@link org.hibernate.Session}. It is not
* this interface ever be exposed to the application. It <b>is</b> * intended that this interface ever be exposed to the application.
* intended that users implement this interface to provide * It <em>is</em> intended that users implement this interface to
* custom identifier generation strategies. * provide custom identifier generation strategies.
* <p> * <p>
* Implementors should provide a public default constructor. * Implementors should provide a public default constructor.
* <p> * <p>
* Implementations that accept configuration parameters should * Implementations that accept configuration parameters should also
* also implement {@code Configurable}. * implement {@link Configurable}.
* <p> * <p>
* Implementors <em>must</em> be thread-safe * Implementors <em>must</em> be thread-safe
* *
@ -36,7 +39,7 @@ import org.hibernate.type.Type;
* *
* @see PersistentIdentifierGenerator * @see PersistentIdentifierGenerator
*/ */
public interface IdentifierGenerator extends Configurable, ExportableProducer { public interface IdentifierGenerator extends InMemoryValueGenerationStrategy, ExportableProducer, Configurable {
/** /**
* The configuration parameter holding the entity name * The configuration parameter holding the entity name
*/ */
@ -48,8 +51,11 @@ public interface IdentifierGenerator extends Configurable, ExportableProducer {
String JPA_ENTITY_NAME = "jpa_entity_name"; String JPA_ENTITY_NAME = "jpa_entity_name";
/** /**
* Used as a key to pass the name used as {@link GeneratedValue#generator()} to the * The configuration parameter holding the name of this
* {@link IdentifierGenerator} as it is configured. * identifier generator.
*
* @see org.hibernate.annotations.GenericGenerator#name()
* @see jakarta.persistence.GeneratedValue#generator().
*/ */
String GENERATOR_NAME = "GENERATOR_NAME"; String GENERATOR_NAME = "GENERATOR_NAME";
@ -62,7 +68,8 @@ public interface IdentifierGenerator extends Configurable, ExportableProducer {
* Configure this instance, given the value of parameters * Configure this instance, given the value of parameters
* specified by the user as {@code &lt;param&gt;} elements. * specified by the user as {@code &lt;param&gt;} elements.
* <p> * <p>
* 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 type The id property type descriptor
* @param params param values, keyed by parameter name * @param params param values, keyed by parameter name
@ -70,13 +77,15 @@ public interface IdentifierGenerator extends Configurable, ExportableProducer {
* @throws MappingException If configuration fails. * @throws MappingException If configuration fails.
*/ */
@Override @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.
* <p> * <p>
* 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 * @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.
* <p> * <p>
* 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 * @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 * @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. * Check if JDBC batch inserts are supported.
* *
* @return 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() { default boolean supportsJdbcBatchInserts() {
return true; return true;
} }

View File

@ -8,16 +8,14 @@ package org.hibernate.id;
import java.util.Properties; import java.util.Properties;
import org.hibernate.HibernateException;
import org.hibernate.dialect.Dialect;
import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistry;
import org.hibernate.type.Type; import org.hibernate.type.Type;
/** /**
* An {@code IdentifierGenerator} that requires creation of database objects. * An {@link IdentifierGenerator} that requires creation of database objects.
* <p> * <p>
* All {@code PersistentIdentifierGenerator}s have access to a special mapping parameter * All instances have access to a special mapping parameter in their
* in their {@link #configure(Type, Properties, ServiceRegistry)} method: schema * {@link #configure(Type, Properties, ServiceRegistry)} method: schema
* *
* @author Gavin King * @author Gavin King
* @author Steve Ebersole * @author Steve Ebersole

View File

@ -40,10 +40,10 @@ public interface GeneratedValueResolver {
} }
else { else {
InMemoryValueGenerationStrategy generation = (InMemoryValueGenerationStrategy) valueGeneration; InMemoryValueGenerationStrategy generation = (InMemoryValueGenerationStrategy) valueGeneration;
return new InMemoryGeneratedValueResolver( generation.getValueGenerator(), requestedTiming ); return new InMemoryGeneratedValueResolver( generation, requestedTiming );
} }
} }
GenerationTiming getGenerationTiming(); GenerationTiming getGenerationTiming();
Object resolveGeneratedValue(Object[] row, Object entity, SharedSessionContractImplementor session); Object resolveGeneratedValue(Object[] row, Object entity, SharedSessionContractImplementor session, Object currentValue);
} }

View File

@ -32,7 +32,7 @@ public class InDatabaseGeneratedValueResolver implements GeneratedValueResolver
} }
@Override @Override
public Object resolveGeneratedValue(Object[] row, Object entity, SharedSessionContractImplementor session) { public Object resolveGeneratedValue(Object[] row, Object entity, SharedSessionContractImplementor session, Object currentValue) {
return row[resultPosition]; return row[resultPosition];
} }
} }

View File

@ -7,10 +7,9 @@
package org.hibernate.metamodel.mapping; package org.hibernate.metamodel.mapping;
import org.hibernate.Internal; import org.hibernate.Internal;
import org.hibernate.Session;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.tuple.GenerationTiming; import org.hibernate.tuple.GenerationTiming;
import org.hibernate.tuple.ValueGenerator; import org.hibernate.tuple.InMemoryValueGenerationStrategy;
/** /**
* GeneratedValueResolver impl for in-memory generation * GeneratedValueResolver impl for in-memory generation
@ -20,9 +19,9 @@ import org.hibernate.tuple.ValueGenerator;
@Internal @Internal
public class InMemoryGeneratedValueResolver implements GeneratedValueResolver { public class InMemoryGeneratedValueResolver implements GeneratedValueResolver {
private final GenerationTiming generationTiming; 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.valueGenerator = valueGenerator;
this.generationTiming = generationTiming; this.generationTiming = generationTiming;
} }
@ -33,7 +32,7 @@ public class InMemoryGeneratedValueResolver implements GeneratedValueResolver {
} }
@Override @Override
public Object resolveGeneratedValue(Object[] row, Object entity, SharedSessionContractImplementor session) { public Object resolveGeneratedValue(Object[] row, Object entity, SharedSessionContractImplementor session, Object currentValue) {
return valueGenerator.generateValue( (Session) session, entity ); return valueGenerator.generate( session, entity, currentValue );
} }
} }

View File

@ -175,7 +175,7 @@ public class GeneratedValuesProcessor {
for ( int i = 0; i < valueDescriptors.size(); i++ ) { for ( int i = 0; i < valueDescriptors.size(); i++ ) {
final GeneratedValueDescriptor descriptor = valueDescriptors.get( 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; state[ descriptor.attribute.getStateArrayPosition() ] = generatedValue;
descriptor.attribute.getAttributeMetadataAccess() descriptor.attribute.getAttributeMetadataAccess()
.resolveAttributeMetadata( entityDescriptor ) .resolveAttributeMetadata( entityDescriptor )

View File

@ -26,7 +26,7 @@ public class NoGeneratedValueResolver implements GeneratedValueResolver {
} }
@Override @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" ); throw new UnsupportedMappingException( "NoGeneratedValueResolver does not support generated values" );
} }
} }

View File

@ -10,7 +10,6 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.hibernate.Internal; import org.hibernate.Internal;
import org.hibernate.Session;
import org.hibernate.engine.jdbc.batch.internal.BasicBatchKey; import org.hibernate.engine.jdbc.batch.internal.BasicBatchKey;
import org.hibernate.engine.jdbc.mutation.JdbcValueBindings; import org.hibernate.engine.jdbc.mutation.JdbcValueBindings;
import org.hibernate.engine.jdbc.mutation.MutationExecutor; import org.hibernate.engine.jdbc.mutation.MutationExecutor;
@ -104,7 +103,7 @@ public class InsertCoordinator extends AbstractMutationCoordinator {
final InMemoryValueGenerationStrategy[] strategies = entityMetamodel.getInMemoryValueGenerationStrategies(); final InMemoryValueGenerationStrategy[] strategies = entityMetamodel.getInMemoryValueGenerationStrategies();
for ( int i = 0; i < strategies.length; i++ ) { for ( int i = 0; i < strategies.length; i++ ) {
if ( strategies[i] != null && strategies[i].getGenerationTiming().includesInsert() ) { 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] ); entityPersister().setPropertyValue( entity, i, values[i] );
} }
} }

View File

@ -14,7 +14,6 @@ import java.util.Set;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.Internal; import org.hibernate.Internal;
import org.hibernate.Session;
import org.hibernate.engine.OptimisticLockStyle; import org.hibernate.engine.OptimisticLockStyle;
import org.hibernate.engine.jdbc.batch.internal.BasicBatchKey; import org.hibernate.engine.jdbc.batch.internal.BasicBatchKey;
import org.hibernate.engine.jdbc.batch.spi.BatchKey; 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++ ) { for ( int i = 0; i < valueGenerationStrategies.length; i++ ) {
if ( valueGenerationStrategies[i] != null if ( valueGenerationStrategies[i] != null
&& valueGenerationStrategies[i].getGenerationTiming().includesUpdate() ) { && valueGenerationStrategies[i].getGenerationTiming().includesUpdate() ) {
newValues[i] = valueGenerationStrategies[i].getValueGenerator().generateValue( newValues[i] = valueGenerationStrategies[i].generate( session, object, newValues[i] );
(Session) session,
object
);
entityPersister().setPropertyValue( object, i, newValues[i] ); entityPersister().setPropertyValue( object, i, newValues[i] );
fieldsPreUpdateNeeded[count++] = i; fieldsPreUpdateNeeded[count++] = i;
} }

View File

@ -6,6 +6,8 @@
*/ */
package org.hibernate.tuple; package org.hibernate.tuple;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
/** /**
* Java value generation is the responsibility of an associated {@link ValueGenerator}. * 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 * 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 * @since 6.2
*/ */
public interface InMemoryValueGenerationStrategy extends ValueGenerationStrategy { public interface InMemoryValueGenerationStrategy extends ValueGenerationStrategy {
/** /**
* Obtain the {@linkplain ValueGenerator Java value generator}, if the value is generated in * Generate a value.
* Java, or return {@code null} if the value is generated by the database.
* *
* @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() { default boolean generatedByDatabase() {
return false; return false;

View File

@ -8,10 +8,10 @@ package org.hibernate.tuple;
import org.hibernate.MappingException; import org.hibernate.MappingException;
import org.hibernate.PropertyValueException; import org.hibernate.PropertyValueException;
import org.hibernate.Session;
import org.hibernate.annotations.TenantId; import org.hibernate.annotations.TenantId;
import org.hibernate.context.spi.CurrentTenantIdentifierResolver; import org.hibernate.context.spi.CurrentTenantIdentifierResolver;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.type.descriptor.java.JavaType; import org.hibernate.type.descriptor.java.JavaType;
/** /**
@ -20,7 +20,7 @@ import org.hibernate.type.descriptor.java.JavaType;
* @author Gavin King * @author Gavin King
*/ */
public class TenantIdGeneration public class TenantIdGeneration
implements AnnotationValueGenerationStrategy<TenantId>, InMemoryValueGenerationStrategy, ValueGenerator<Object> { implements AnnotationValueGenerationStrategy<TenantId>, InMemoryValueGenerationStrategy {
private String entityName; private String entityName;
private String propertyName; private String propertyName;
@ -39,13 +39,8 @@ public class TenantIdGeneration
} }
@Override @Override
public ValueGenerator<?> getValueGenerator() { public Object generate(SharedSessionContractImplementor session, Object owner, Object currentValue) {
return this; SessionFactoryImplementor sessionFactory = session.getSessionFactory();
}
@Override
public Object generateValue(Session session, Object owner, Object currentValue) {
SessionFactoryImplementor sessionFactory = (SessionFactoryImplementor) session.getSessionFactory();
JavaType<Object> descriptor = sessionFactory.getTypeConfiguration().getJavaTypeRegistry() JavaType<Object> descriptor = sessionFactory.getTypeConfiguration().getJavaTypeRegistry()
.findDescriptor(propertyType); .findDescriptor(propertyType);
if ( descriptor==null ) { if ( descriptor==null ) {
@ -70,9 +65,4 @@ public class TenantIdGeneration
} }
return tenantId == null ? null : descriptor.fromString(tenantId); //convert to the model type return tenantId == null ? null : descriptor.fromString(tenantId); //convert to the model type
} }
@Override
public Object generateValue(Session session, Object owner) {
throw new UnsupportedOperationException();
}
} }

View File

@ -6,7 +6,9 @@
*/ */
package org.hibernate.tuple; package org.hibernate.tuple;
import org.hibernate.Session;
import org.hibernate.dialect.Dialect; 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 * 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 * @author Gavin King
*/ */
public interface ValueGeneration extends InMemoryValueGenerationStrategy, InDatabaseValueGenerationStrategy { 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 * 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 * SQL {@code insert} or {@code update} statement, in the case where the value is generated

View File

@ -52,8 +52,9 @@ public interface ValueGenerationStrategy extends Serializable {
/** /**
* Determines if the property value is generated in Java, or by the database. * 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 * @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(); boolean generatedByDatabase();
} }

View File

@ -34,6 +34,6 @@ public interface ValueGenerator<T> {
* @return The generated value * @return The generated value
*/ */
default T generateValue(Session session, Object owner, Object currentValue) { default T generateValue(Session session, Object owner, Object currentValue) {
return generateValue(session, owner); return generateValue( session, owner );
} }
} }

View File

@ -9,7 +9,9 @@ package org.hibernate.tuple;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.annotations.GeneratorType; import org.hibernate.annotations.GeneratorType;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.internal.util.ReflectHelper; import org.hibernate.internal.util.ReflectHelper;
/** /**
@ -21,11 +23,17 @@ public class VmValueGeneration
implements AnnotationValueGenerationStrategy<GeneratorType>, InMemoryValueGenerationStrategy { implements AnnotationValueGenerationStrategy<GeneratorType>, InMemoryValueGenerationStrategy {
private GenerationTiming generationTiming; private GenerationTiming generationTiming;
private Constructor<? extends ValueGenerator<?>> constructor; ValueGenerator<?> generator;
@Override @Override
public void initialize(GeneratorType annotation, Class<?> propertyType, String entityName, String propertyName) { public void initialize(GeneratorType annotation, Class<?> propertyType, String entityName, String propertyName) {
constructor = ReflectHelper.getDefaultConstructor( annotation.type() ); Constructor<? extends ValueGenerator<?>> 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(); generationTiming = annotation.when().getEquivalent();
} }
@ -35,12 +43,7 @@ public class VmValueGeneration
} }
@Override @Override
public ValueGenerator<?> getValueGenerator() { public Object generate(SharedSessionContractImplementor session, Object owner, Object currentValue) {
try { return generator.generateValue( (Session) session, owner, currentValue );
return constructor.newInstance();
}
catch (Exception e) {
throw new HibernateException( "Couldn't instantiate value generator", e );
}
} }
} }

View File

@ -29,6 +29,7 @@ import org.hibernate.engine.spi.CascadeStyle;
import org.hibernate.engine.spi.CascadeStyles; import org.hibernate.engine.spi.CascadeStyles;
import org.hibernate.engine.spi.CascadingActions; import org.hibernate.engine.spi.CascadingActions;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.ReflectHelper; import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.internal.util.collections.ArrayHelper; 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.InMemoryValueGenerationStrategy;
import org.hibernate.tuple.NonIdentifierAttribute; import org.hibernate.tuple.NonIdentifierAttribute;
import org.hibernate.tuple.PropertyFactory; import org.hibernate.tuple.PropertyFactory;
import org.hibernate.tuple.ValueGenerator;
import org.hibernate.type.AssociationType; import org.hibernate.type.AssociationType;
import org.hibernate.type.CollectionType; import org.hibernate.type.CollectionType;
import org.hibernate.type.ComponentType; import org.hibernate.type.ComponentType;
@ -304,28 +304,25 @@ public class EntityMetamodel implements Serializable {
inMemoryValueGenerationStrategies[i] = pair.getInMemoryStrategy(); inMemoryValueGenerationStrategies[i] = pair.getInMemoryStrategy();
inDatabaseValueGenerationStrategies[i] = pair.getInDatabaseStrategy(); inDatabaseValueGenerationStrategies[i] = pair.getInDatabaseStrategy();
if ( pair.getInMemoryStrategy() != null ) { if ( pair.getInMemoryStrategy() != null
&& !pair.getInMemoryStrategy().generatedByDatabase() ) {
final GenerationTiming timing = pair.getInMemoryStrategy().getGenerationTiming(); final GenerationTiming timing = pair.getInMemoryStrategy().getGenerationTiming();
if ( timing != GenerationTiming.NEVER ) { // we have some level of generation indicated
final ValueGenerator<?> generator = pair.getInMemoryStrategy().getValueGenerator(); switch ( timing ) {
if ( generator != null ) { case INSERT:
// we have some level of generation indicated foundPreInsertGeneratedValues = true;
switch ( timing ) { break;
case INSERT: case UPDATE:
foundPreInsertGeneratedValues = true; foundPreUpdateGeneratedValues = true;
break; break;
case UPDATE: case ALWAYS:
foundPreUpdateGeneratedValues = true; foundPreInsertGeneratedValues = true;
break; foundPreUpdateGeneratedValues = true;
case ALWAYS: break;
foundPreInsertGeneratedValues = true;
foundPreUpdateGeneratedValues = true;
break;
}
}
} }
} }
if ( pair.getInDatabaseStrategy() != null ) { if ( pair.getInDatabaseStrategy() != null
&& pair.getInDatabaseStrategy().generatedByDatabase() ) {
switch ( pair.getInDatabaseStrategy().getGenerationTiming() ) { switch ( pair.getInDatabaseStrategy().getGenerationTiming() ) {
case INSERT: case INSERT:
foundPostInsertGeneratedValues = true; foundPostInsertGeneratedValues = true;
@ -463,9 +460,7 @@ public class EntityMetamodel implements Serializable {
// the property is generated in full. build the generation strategy pair. // the property is generated in full. build the generation strategy pair.
if ( !valueGeneration.generatedByDatabase() ) { if ( !valueGeneration.generatedByDatabase() ) {
// in-memory generation // in-memory generation
return new GenerationStrategyPair( return new GenerationStrategyPair( (InMemoryValueGenerationStrategy) valueGeneration );
FullInMemoryValueGenerationStrategy.create( (InMemoryValueGenerationStrategy) valueGeneration )
);
} }
else { else {
// in-db generation // in-db generation
@ -503,7 +498,7 @@ public class EntityMetamodel implements Serializable {
this( NoInMemoryValueGenerationStrategy.INSTANCE, NoInDatabaseValueGenerationStrategy.INSTANCE ); this( NoInMemoryValueGenerationStrategy.INSTANCE, NoInDatabaseValueGenerationStrategy.INSTANCE );
} }
public GenerationStrategyPair(FullInMemoryValueGenerationStrategy inMemoryStrategy) { public GenerationStrategyPair(InMemoryValueGenerationStrategy inMemoryStrategy) {
this( inMemoryStrategy, NoInDatabaseValueGenerationStrategy.INSTANCE ); this( inMemoryStrategy, NoInDatabaseValueGenerationStrategy.INSTANCE );
} }
@ -685,38 +680,11 @@ public class EntityMetamodel implements Serializable {
} }
@Override @Override
public ValueGenerator<?> getValueGenerator() { public Object generate(SharedSessionContractImplementor session, Object owner, Object currentValue) {
return null; 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 { private static class NoInDatabaseValueGenerationStrategy implements InDatabaseValueGenerationStrategy {
/** /**
* Singleton access * Singleton access

View File

@ -19,10 +19,10 @@ import jakarta.persistence.Table;
import org.hibernate.Session; import org.hibernate.Session;
import org.hibernate.annotations.ValueGenerationType; import org.hibernate.annotations.ValueGenerationType;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.tuple.AnnotationValueGenerationStrategy; import org.hibernate.tuple.AnnotationValueGenerationStrategy;
import org.hibernate.tuple.GenerationTiming; import org.hibernate.tuple.GenerationTiming;
import org.hibernate.tuple.InMemoryValueGenerationStrategy; import org.hibernate.tuple.InMemoryValueGenerationStrategy;
import org.hibernate.tuple.ValueGenerator;
import org.hibernate.testing.orm.junit.DomainModel; import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.SessionFactory; import org.hibernate.testing.orm.junit.SessionFactory;
@ -66,9 +66,7 @@ public class GeneratedUuidTests {
assertThat( merged ).isNotNull(); assertThat( merged ).isNotNull();
// lastly, make sure we can load it.. // lastly, make sure we can load it..
final GeneratedUuidEntity loaded = scope.fromTransaction( (session) -> { final GeneratedUuidEntity loaded = scope.fromTransaction( (session) -> session.get( GeneratedUuidEntity.class, 1 ));
return session.get( GeneratedUuidEntity.class, 1 );
} );
assertThat( loaded ).isNotNull(); assertThat( loaded ).isNotNull();
@ -88,7 +86,7 @@ public class GeneratedUuidTests {
//tag::mapping-generated-custom-ex3[] //tag::mapping-generated-custom-ex3[]
public static class UuidValueGeneration public static class UuidValueGeneration
implements AnnotationValueGenerationStrategy<GeneratedUuidValue>, InMemoryValueGenerationStrategy, ValueGenerator<UUID> { implements AnnotationValueGenerationStrategy<GeneratedUuidValue>, InMemoryValueGenerationStrategy {
private GenerationTiming timing; private GenerationTiming timing;
@Override @Override
@ -102,12 +100,7 @@ public class GeneratedUuidTests {
} }
@Override @Override
public ValueGenerator<?> getValueGenerator() { public Object generate(SharedSessionContractImplementor session, Object owner, Object currentValue) {
return this;
}
@Override
public UUID generateValue(Session session, Object owner) {
return UUID.randomUUID(); return UUID.randomUUID();
} }
} }