HHH-15789 make IdentifierGenerator into a sort of value generator
This commit is contained in:
parent
1c083a5863
commit
82c68d93e9
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 <param>} elements.
|
* specified by the user as {@code <param>} 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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 )
|
||||||
|
|
|
@ -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" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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] );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue