HHH-15789 allow any InMemoryGenerator to generate ids

This commit is contained in:
Gavin 2022-11-30 21:30:45 +01:00 committed by Gavin King
parent 7f72696fff
commit 26e7393775
47 changed files with 763 additions and 560 deletions

View File

@ -6,7 +6,7 @@
*/ */
package org.hibernate.annotations; package org.hibernate.annotations;
import org.hibernate.id.IdentifierGenerator; import org.hibernate.tuple.InMemoryGenerator;
import java.lang.annotation.Repeatable; import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
@ -74,12 +74,11 @@ public @interface GenericGenerator {
*/ */
String name(); String name();
/** /**
* The type of identifier generator, a class implementing * The type of identifier generator, a class implementing {@link InMemoryGenerator}.
* {@link org.hibernate.id.IdentifierGenerator}.
* *
* @since 6.2 * @since 6.2
*/ */
Class<? extends IdentifierGenerator> type() default IdentifierGenerator.class; Class<? extends InMemoryGenerator> type() default InMemoryGenerator.class;
/** /**
* The type of identifier generator, the name of either: * The type of identifier generator, the name of either:
* <ul> * <ul>

View File

@ -11,6 +11,7 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import org.hibernate.id.IdentifierGenerator; import org.hibernate.id.IdentifierGenerator;
import org.hibernate.tuple.InMemoryGenerator;
import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME; import static java.lang.annotation.RetentionPolicy.RUNTIME;
@ -63,8 +64,8 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Retention(RUNTIME) @Retention(RUNTIME)
public @interface IdGeneratorType { public @interface IdGeneratorType {
/** /**
* A class that implements {@link IdentifierGenerator} and has a * A class that implements {@link InMemoryGenerator} and has a constructor
* constructor with the signature: * with the signature:
* <pre>{@code * <pre>{@code
* public GeneratorType(AnnotationType config, Member idMember, * public GeneratorType(AnnotationType config, Member idMember,
* CustomIdGeneratorCreationContext creationContext) * CustomIdGeneratorCreationContext creationContext)
@ -73,5 +74,5 @@ public @interface IdGeneratorType {
* {@code IdentifierGenerator}, and {@code AnnotationType} is the * {@code IdentifierGenerator}, and {@code AnnotationType} is the
* annotation type to which this annotation was applied. * annotation type to which this annotation was applied.
*/ */
Class<? extends IdentifierGenerator> value(); Class<? extends InMemoryGenerator> value();
} }

View File

@ -46,6 +46,7 @@ import org.hibernate.boot.model.naming.ImplicitIndexNameSource;
import org.hibernate.boot.model.naming.ImplicitUniqueKeyNameSource; import org.hibernate.boot.model.naming.ImplicitUniqueKeyNameSource;
import org.hibernate.boot.model.relational.AuxiliaryDatabaseObject; import org.hibernate.boot.model.relational.AuxiliaryDatabaseObject;
import org.hibernate.boot.model.relational.Database; import org.hibernate.boot.model.relational.Database;
import org.hibernate.boot.model.relational.ExportableProducer;
import org.hibernate.boot.model.relational.Namespace; import org.hibernate.boot.model.relational.Namespace;
import org.hibernate.boot.model.relational.QualifiedTableName; import org.hibernate.boot.model.relational.QualifiedTableName;
import org.hibernate.boot.model.source.internal.ImplicitColumnNamingSecondPass; import org.hibernate.boot.model.source.internal.ImplicitColumnNamingSecondPass;
@ -102,6 +103,7 @@ import org.hibernate.metamodel.CollectionClassification;
import org.hibernate.metamodel.spi.EmbeddableInstantiator; import org.hibernate.metamodel.spi.EmbeddableInstantiator;
import org.hibernate.query.named.NamedObjectRepository; import org.hibernate.query.named.NamedObjectRepository;
import org.hibernate.query.sqm.function.SqmFunctionDescriptor; import org.hibernate.query.sqm.function.SqmFunctionDescriptor;
import org.hibernate.tuple.InMemoryGenerator;
import org.hibernate.type.descriptor.java.JavaType; import org.hibernate.type.descriptor.java.JavaType;
import org.hibernate.type.descriptor.jdbc.JdbcType; import org.hibernate.type.descriptor.jdbc.JdbcType;
import org.hibernate.type.spi.TypeConfiguration; import org.hibernate.type.spi.TypeConfiguration;
@ -2314,13 +2316,15 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector
// It was done this way in the old code too, so no "regression" here; but // It was done this way in the old code too, so no "regression" here; but
// it could be done better // it could be done better
try { try {
final IdentifierGenerator ig = identifierValueBinding.createIdentifierGenerator( final InMemoryGenerator generator = identifierValueBinding.createIdentifierGenerator(
bootstrapContext.getIdentifierGeneratorFactory(), bootstrapContext.getIdentifierGeneratorFactory(),
dialect, dialect,
entityBinding entityBinding
); );
ig.registerExportables( getDatabase() ); if ( generator instanceof ExportableProducer ) {
( (ExportableProducer) generator ).registerExportables( getDatabase() );
}
} }
catch (MappingException e) { catch (MappingException e) {
// ignore this for now. The reasoning being "non-reflective" binding as needed // ignore this for now. The reasoning being "non-reflective" binding as needed

View File

@ -7,10 +7,20 @@
package org.hibernate.boot.model; package org.hibernate.boot.model;
import java.io.Serializable; import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Index;
import jakarta.persistence.SequenceGenerator;
import jakarta.persistence.TableGenerator;
import jakarta.persistence.UniqueConstraint;
import org.hibernate.AssertionFailure;
import org.hibernate.Internal;
import org.hibernate.id.IdentifierGenerator;
import org.hibernate.internal.util.collections.CollectionHelper; import org.hibernate.internal.util.collections.CollectionHelper;
import static java.util.Collections.emptyMap; import static java.util.Collections.emptyMap;
@ -74,6 +84,171 @@ public class IdentifierGeneratorDefinition implements Serializable {
return parameters; return parameters;
} }
@Internal
public static IdentifierGeneratorDefinition createImplicit(
String name,
Class<?> idType,
String generatorName,
IdGeneratorStrategyInterpreter generationInterpreter,
GenerationType generationType) {
// If we were unable to locate an actual matching named generator assume
// a sequence/table of the given name, make one based on GenerationType.
if ( generationType == null) {
return buildSequenceGeneratorDefinition( name, generationInterpreter );
}
final String strategyName;
switch ( generationType ) {
case SEQUENCE:
return buildSequenceGeneratorDefinition( name, generationInterpreter );
case TABLE:
return buildTableGeneratorDefinition( name, generationInterpreter );
// really AUTO and IDENTITY work the same in this respect, aside from the actual strategy name
case IDENTITY:
strategyName = "identity";
break;
case AUTO:
strategyName = generationInterpreter.determineGeneratorName(
generationType,
new IdGeneratorStrategyInterpreter.GeneratorNameDeterminationContext() {
@Override
public Class<?> getIdType() {
return idType;
}
@Override
public String getGeneratedValueGeneratorName() {
return generatorName;
}
}
);
break;
default:
throw new AssertionFailure( "unknown generator type: " + generationType );
}
return new IdentifierGeneratorDefinition(
name,
strategyName,
Collections.singletonMap( IdentifierGenerator.GENERATOR_NAME, name )
);
}
private static IdentifierGeneratorDefinition buildTableGeneratorDefinition(String name, IdGeneratorStrategyInterpreter generationInterpreter) {
final Builder builder = new Builder();
generationInterpreter.interpretTableGenerator(
new TableGenerator() {
@Override
public String name() {
return name;
}
@Override
public String table() {
return "";
}
@Override
public int initialValue() {
return 0;
}
@Override
public int allocationSize() {
return 50;
}
@Override
public String catalog() {
return "";
}
@Override
public String schema() {
return "";
}
@Override
public String pkColumnName() {
return "";
}
@Override
public String valueColumnName() {
return "";
}
@Override
public String pkColumnValue() {
return "";
}
@Override
public UniqueConstraint[] uniqueConstraints() {
return new UniqueConstraint[0];
}
@Override
public Index[] indexes() {
return new Index[0];
}
@Override
public Class<? extends Annotation> annotationType() {
return TableGenerator.class;
}
},
builder
);
return builder.build();
}
private static IdentifierGeneratorDefinition buildSequenceGeneratorDefinition(String name, IdGeneratorStrategyInterpreter generationInterpreter) {
final Builder builder = new Builder();
generationInterpreter.interpretSequenceGenerator(
new SequenceGenerator() {
@Override
public String name() {
return name;
}
@Override
public String sequenceName() {
return "";
}
@Override
public String catalog() {
return "";
}
@Override
public String schema() {
return "";
}
@Override
public int initialValue() {
return 1;
}
@Override
public int allocationSize() {
return 50;
}
@Override
public Class<? extends Annotation> annotationType() {
return SequenceGenerator.class;
}
},
builder
);
return builder.build();
}
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if ( this == o ) { if ( this == o ) {

View File

@ -53,6 +53,7 @@ import org.hibernate.annotations.ParamDef;
import org.hibernate.annotations.Parameter; import org.hibernate.annotations.Parameter;
import org.hibernate.annotations.Parent; import org.hibernate.annotations.Parent;
import org.hibernate.annotations.TimeZoneStorage; import org.hibernate.annotations.TimeZoneStorage;
import org.hibernate.annotations.ValueGenerationType;
import org.hibernate.annotations.common.reflection.ReflectionManager; import org.hibernate.annotations.common.reflection.ReflectionManager;
import org.hibernate.annotations.common.reflection.XAnnotatedElement; import org.hibernate.annotations.common.reflection.XAnnotatedElement;
import org.hibernate.annotations.common.reflection.XClass; import org.hibernate.annotations.common.reflection.XClass;
@ -91,6 +92,7 @@ import org.hibernate.property.access.internal.PropertyAccessStrategyMixedImpl;
import org.hibernate.property.access.spi.PropertyAccessStrategy; import org.hibernate.property.access.spi.PropertyAccessStrategy;
import org.hibernate.resource.beans.spi.ManagedBean; import org.hibernate.resource.beans.spi.ManagedBean;
import org.hibernate.resource.beans.spi.ManagedBeanRegistry; import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
import org.hibernate.tuple.InMemoryGenerator;
import org.hibernate.type.BasicType; import org.hibernate.type.BasicType;
import org.hibernate.type.CustomType; import org.hibernate.type.CustomType;
import org.hibernate.type.descriptor.java.BasicJavaType; import org.hibernate.type.descriptor.java.BasicJavaType;
@ -152,6 +154,7 @@ import static org.hibernate.cfg.InheritanceState.getInheritanceStateOfSuperEntit
import static org.hibernate.cfg.InheritanceState.getSuperclassInheritanceState; import static org.hibernate.cfg.InheritanceState.getSuperclassInheritanceState;
import static org.hibernate.cfg.PropertyHolderBuilder.buildPropertyHolder; import static org.hibernate.cfg.PropertyHolderBuilder.buildPropertyHolder;
import static org.hibernate.cfg.annotations.HCANNHelper.findContainingAnnotation; import static org.hibernate.cfg.annotations.HCANNHelper.findContainingAnnotation;
import static org.hibernate.cfg.annotations.PropertyBinder.generatorCreator;
import static org.hibernate.cfg.annotations.PropertyBinder.identifierGeneratorCreator; import static org.hibernate.cfg.annotations.PropertyBinder.identifierGeneratorCreator;
import static org.hibernate.internal.CoreLogging.messageLogger; import static org.hibernate.internal.CoreLogging.messageLogger;
import static org.hibernate.mapping.Constraint.hashedName; import static org.hibernate.mapping.Constraint.hashedName;
@ -477,10 +480,10 @@ public final class AnnotationBinder {
else if ( generatorAnnotation instanceof GenericGenerator ) { else if ( generatorAnnotation instanceof GenericGenerator ) {
final GenericGenerator genericGenerator = (GenericGenerator) generatorAnnotation; final GenericGenerator genericGenerator = (GenericGenerator) generatorAnnotation;
definitionBuilder.setName( genericGenerator.name() ); definitionBuilder.setName( genericGenerator.name() );
final String strategy = genericGenerator.type().equals(IdentifierGenerator.class) final String strategy = genericGenerator.type().equals(InMemoryGenerator.class)
? genericGenerator.strategy() ? genericGenerator.strategy()
: genericGenerator.type().getName(); : genericGenerator.type().getName();
definitionBuilder.setStrategy(strategy); definitionBuilder.setStrategy( strategy );
for ( Parameter parameter : genericGenerator.parameters() ) { for ( Parameter parameter : genericGenerator.parameters() ) {
definitionBuilder.addParam( parameter.name(), parameter.value() ); definitionBuilder.addParam( parameter.name(), parameter.value() );
} }
@ -1806,9 +1809,14 @@ public final class AnnotationBinder {
+ "' belongs to an '@IdClass' and may not be annotated '@Id' or '@EmbeddedId'" ); + "' belongs to an '@IdClass' and may not be annotated '@Id' or '@EmbeddedId'" );
} }
final XProperty idProperty = inferredData.getProperty(); final XProperty idProperty = inferredData.getProperty();
final Annotation generatorAnnotation = findContainingAnnotation( idProperty, IdGeneratorType.class ); final Annotation idGeneratorAnnotation = findContainingAnnotation( idProperty, IdGeneratorType.class );
if ( generatorAnnotation != null ) { final Annotation generatorAnnotation = findContainingAnnotation( idProperty, ValueGenerationType.class );
idValue.setCustomIdGeneratorCreator( identifierGeneratorCreator( idProperty, generatorAnnotation ) ); //TODO: validate that we don't have too many generator annotations and throw
if ( idGeneratorAnnotation != null ) {
idValue.setCustomIdGeneratorCreator( identifierGeneratorCreator( idProperty, idGeneratorAnnotation ) );
}
else if ( generatorAnnotation != null ) {
idValue.setCustomGeneratorCreator( generatorCreator( idProperty, generatorAnnotation ) );
} }
else { else {
final XClass entityClass = inferredData.getClassOrElement(); final XClass entityClass = inferredData.getClassOrElement();

View File

@ -11,7 +11,6 @@ import java.lang.annotation.Repeatable;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
@ -41,8 +40,6 @@ import org.hibernate.annotations.SqlFragmentAlias;
import org.hibernate.annotations.common.reflection.XAnnotatedElement; import org.hibernate.annotations.common.reflection.XAnnotatedElement;
import org.hibernate.annotations.common.reflection.XClass; import org.hibernate.annotations.common.reflection.XClass;
import org.hibernate.annotations.common.reflection.XProperty; import org.hibernate.annotations.common.reflection.XProperty;
import org.hibernate.boot.model.IdGeneratorStrategyInterpreter;
import org.hibernate.boot.model.IdGeneratorStrategyInterpreter.GeneratorNameDeterminationContext;
import org.hibernate.boot.model.IdentifierGeneratorDefinition; import org.hibernate.boot.model.IdentifierGeneratorDefinition;
import org.hibernate.boot.spi.InFlightMetadataCollector; import org.hibernate.boot.spi.InFlightMetadataCollector;
import org.hibernate.boot.spi.MetadataBuildingContext; import org.hibernate.boot.spi.MetadataBuildingContext;
@ -74,10 +71,6 @@ import org.jboss.logging.Logger;
import jakarta.persistence.GeneratedValue; import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType; import jakarta.persistence.GenerationType;
import jakarta.persistence.Index;
import jakarta.persistence.SequenceGenerator;
import jakarta.persistence.TableGenerator;
import jakarta.persistence.UniqueConstraint;
import static org.hibernate.cfg.AnnotatedColumn.buildColumnOrFormulaFromAnnotation; import static org.hibernate.cfg.AnnotatedColumn.buildColumnOrFormulaFromAnnotation;
import static org.hibernate.internal.util.StringHelper.isNotEmpty; import static org.hibernate.internal.util.StringHelper.isNotEmpty;
@ -777,7 +770,7 @@ public class BinderHelper {
if ( !isEmptyAnnotationValue( generatorName ) ) { if ( !isEmptyAnnotationValue( generatorName ) ) {
//we have a named generator //we have a named generator
final IdentifierGeneratorDefinition definition = getIdentifierGenerator( final IdentifierGeneratorDefinition definition = makeIdentifierGeneratorDefinition(
generatorName, generatorName,
property, property,
localGenerators, localGenerators,
@ -823,7 +816,7 @@ public class BinderHelper {
makeIdGenerator( id, idXProperty, generatorType, generatorName, buildingContext, localIdentifiers ); makeIdGenerator( id, idXProperty, generatorType, generatorName, buildingContext, localIdentifiers );
} }
private static IdentifierGeneratorDefinition getIdentifierGenerator( private static IdentifierGeneratorDefinition makeIdentifierGeneratorDefinition(
String name, String name,
XProperty idXProperty, XProperty idXProperty,
Map<String, IdentifierGeneratorDefinition> localGenerators, Map<String, IdentifierGeneratorDefinition> localGenerators,
@ -843,174 +836,21 @@ public class BinderHelper {
log.debugf( "Could not resolve explicit IdentifierGeneratorDefinition - using implicit interpretation (%s)", name ); log.debugf( "Could not resolve explicit IdentifierGeneratorDefinition - using implicit interpretation (%s)", name );
// If we were unable to locate an actual matching named generator assume a sequence/table of the given name. final GeneratedValue generatedValue = idXProperty.getAnnotation( GeneratedValue.class );
// this really needs access to the `jakarta.persistence.GenerationType` to work completely properly if ( generatedValue == null ) {
//
// (the crux of HHH-12122)
// temporarily, in lieu of having access to GenerationType, assume the EnhancedSequenceGenerator
// for the purpose of testing the feasibility of the approach
final GeneratedValue generatedValueAnn = idXProperty.getAnnotation( GeneratedValue.class );
if ( generatedValueAnn == null ) {
// this should really never happen, but it's easy to protect against it... // this should really never happen, but it's easy to protect against it...
return new IdentifierGeneratorDefinition( "assigned", "assigned" ); return new IdentifierGeneratorDefinition( "assigned", "assigned" );
} }
final IdGeneratorStrategyInterpreter generationInterpreter = return IdentifierGeneratorDefinition.createImplicit(
buildingContext.getBuildingOptions().getIdGenerationTypeInterpreter();
final GenerationType generationType = interpretGenerationType( generatedValueAnn );
if ( generationType == null || generationType == GenerationType.SEQUENCE ) {
// NOTE : `null` will ultimately be interpreted as "hibernate_sequence"
log.debugf( "Building implicit sequence-based IdentifierGeneratorDefinition (%s)", name );
final IdentifierGeneratorDefinition.Builder builder = new IdentifierGeneratorDefinition.Builder();
generationInterpreter.interpretSequenceGenerator(
new SequenceGenerator() {
@Override
public String name() {
return name;
}
@Override
public String sequenceName() {
return "";
}
@Override
public String catalog() {
return "";
}
@Override
public String schema() {
return "";
}
@Override
public int initialValue() {
return 1;
}
@Override
public int allocationSize() {
return 50;
}
@Override
public Class<? extends Annotation> annotationType() {
return SequenceGenerator.class;
}
},
builder
);
return builder.build();
}
else if ( generationType == GenerationType.TABLE ) {
// NOTE : `null` will ultimately be interpreted as "hibernate_sequence"
log.debugf( "Building implicit table-based IdentifierGeneratorDefinition (%s)", name );
final IdentifierGeneratorDefinition.Builder builder = new IdentifierGeneratorDefinition.Builder();
generationInterpreter.interpretTableGenerator(
new TableGenerator() {
@Override
public String name() {
return name;
}
@Override
public String table() {
return "";
}
@Override
public int initialValue() {
return 0;
}
@Override
public int allocationSize() {
return 50;
}
@Override
public String catalog() {
return "";
}
@Override
public String schema() {
return "";
}
@Override
public String pkColumnName() {
return "";
}
@Override
public String valueColumnName() {
return "";
}
@Override
public String pkColumnValue() {
return "";
}
@Override
public UniqueConstraint[] uniqueConstraints() {
return new UniqueConstraint[0];
}
@Override
public Index[] indexes() {
return new Index[0];
}
@Override
public Class<? extends Annotation> annotationType() {
return TableGenerator.class;
}
},
builder
);
return builder.build();
}
// really AUTO and IDENTITY work the same in this respect, aside from the actual strategy name
final String strategyName;
if ( generationType == GenerationType.IDENTITY ) {
strategyName = "identity";
}
else {
strategyName = generationInterpreter.determineGeneratorName(
generationType,
new GeneratorNameDeterminationContext() {
@Override
public Class<?> getIdType() {
return buildingContext
.getBootstrapContext()
.getReflectionManager()
.toClass( idXProperty.getType() );
}
@Override
public String getGeneratedValueGeneratorName() {
return generatedValueAnn.generator();
}
}
);
}
log.debugf( "Building implicit generic IdentifierGeneratorDefinition (%s) : %s", name, strategyName );
return new IdentifierGeneratorDefinition(
name, name,
strategyName, buildingContext
Collections.singletonMap( IdentifierGenerator.GENERATOR_NAME, name ) .getBootstrapContext()
.getReflectionManager()
.toClass( idXProperty.getType() ),
generatedValue.generator(),
buildingContext.getBuildingOptions().getIdGenerationTypeInterpreter(),
interpretGenerationType( generatedValue )
); );
} }

View File

@ -21,6 +21,7 @@ import org.hibernate.annotations.OptimisticLock;
import org.hibernate.annotations.ValueGenerationType; import org.hibernate.annotations.ValueGenerationType;
import org.hibernate.annotations.common.reflection.XClass; import org.hibernate.annotations.common.reflection.XClass;
import org.hibernate.annotations.common.reflection.XProperty; import org.hibernate.annotations.common.reflection.XProperty;
import org.hibernate.boot.model.relational.ExportableProducer;
import org.hibernate.boot.spi.MetadataBuildingContext; import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.cfg.AccessType; import org.hibernate.cfg.AccessType;
import org.hibernate.cfg.AnnotatedColumns; import org.hibernate.cfg.AnnotatedColumns;
@ -37,6 +38,7 @@ import org.hibernate.mapping.Component;
import org.hibernate.mapping.GeneratorCreator; import org.hibernate.mapping.GeneratorCreator;
import org.hibernate.mapping.IdentifierGeneratorCreator; import org.hibernate.mapping.IdentifierGeneratorCreator;
import org.hibernate.mapping.KeyValue; import org.hibernate.mapping.KeyValue;
import org.hibernate.mapping.MappedSuperclass;
import org.hibernate.mapping.Property; import org.hibernate.mapping.Property;
import org.hibernate.mapping.RootClass; import org.hibernate.mapping.RootClass;
import org.hibernate.mapping.SimpleValue; import org.hibernate.mapping.SimpleValue;
@ -49,6 +51,7 @@ import org.hibernate.tuple.Generator;
import org.hibernate.tuple.AttributeBinder; import org.hibernate.tuple.AttributeBinder;
import org.hibernate.tuple.GeneratorCreationContext; import org.hibernate.tuple.GeneratorCreationContext;
import org.hibernate.tuple.GenerationTiming; import org.hibernate.tuple.GenerationTiming;
import org.hibernate.tuple.InMemoryGenerator;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
import java.lang.annotation.Annotation; import java.lang.annotation.Annotation;
@ -168,6 +171,38 @@ public class PropertyBinder {
this.declaringClassSet = true; this.declaringClassSet = true;
} }
private boolean isToOneValue(Value value) {
return value instanceof ToOne;
}
public void setProperty(XProperty property) {
this.property = property;
}
public void setReturnedClass(XClass returnedClass) {
this.returnedClass = returnedClass;
}
public BasicValueBinder getBasicValueBinder() {
return basicValueBinder;
}
public Value getValue() {
return value;
}
public void setId(boolean id) {
this.isId = id;
}
public boolean isId() {
return isId;
}
public void setInheritanceStatePerClass(Map<XClass, InheritanceState> inheritanceStatePerClass) {
this.inheritanceStatePerClass = inheritanceStatePerClass;
}
private void validateBind() { private void validateBind() {
if ( property.isAnnotationPresent( Immutable.class ) ) { if ( property.isAnnotationPresent( Immutable.class ) ) {
throw new AnnotationException( "Property '" + qualify( holder.getPath(), name ) throw new AnnotationException( "Property '" + qualify( holder.getPath(), name )
@ -243,7 +278,8 @@ public class PropertyBinder {
if ( isId ) { if ( isId ) {
final RootClass rootClass = (RootClass) holder.getPersistentClass(); final RootClass rootClass = (RootClass) holder.getPersistentClass();
//if an xToMany, it has to be wrapped today. //if an xToMany, it has to be wrapped today.
//FIXME this poses a problem as the PK is the class instead of the associated class which is not really compliant with the spec //FIXME this poses a problem as the PK is the class instead of the
// associated class which is not really compliant with the spec
if ( isXToMany || entityBinder.wrapIdsInEmbeddedComponents() ) { if ( isXToMany || entityBinder.wrapIdsInEmbeddedComponents() ) {
Component identifier = (Component) rootClass.getIdentifier(); Component identifier = (Component) rootClass.getIdentifier();
if (identifier == null) { if (identifier == null) {
@ -270,7 +306,7 @@ public class PropertyBinder {
} }
else { else {
rootClass.setIdentifierProperty( prop ); rootClass.setIdentifierProperty( prop );
final org.hibernate.mapping.MappedSuperclass superclass = getMappedSuperclassOrNull( final MappedSuperclass superclass = getMappedSuperclassOrNull(
declaringClass, declaringClass,
inheritanceStatePerClass, inheritanceStatePerClass,
buildingContext buildingContext
@ -343,7 +379,7 @@ public class PropertyBinder {
} }
private void handleNaturalId(Property prop) { private void handleNaturalId(Property prop) {
NaturalId naturalId = property.getAnnotation(NaturalId.class); final NaturalId naturalId = property.getAnnotation(NaturalId.class);
if ( naturalId != null ) { if ( naturalId != null ) {
if ( !entityBinder.isRootEntity() ) { if ( !entityBinder.isRootEntity() ) {
throw new AnnotationException( "Property '" + qualify( holder.getPath(), name ) throw new AnnotationException( "Property '" + qualify( holder.getPath(), name )
@ -415,13 +451,14 @@ public class PropertyBinder {
* Instantiates the given generator annotation type, initializing it with the given instance of the corresponding * Instantiates the given generator annotation type, initializing it with the given instance of the corresponding
* generator annotation and the property's type. * generator annotation and the property's type.
*/ */
private <A extends Annotation> GeneratorCreator generatorCreator(XProperty property, A annotation) { public static GeneratorCreator generatorCreator(XProperty property, Annotation annotation) {
final Member member = HCANNHelper.getUnderlyingMember( property ); final Member member = HCANNHelper.getUnderlyingMember( property );
final Class<? extends Annotation> annotationType = annotation.annotationType(); final Class<? extends Annotation> annotationType = annotation.annotationType();
final ValueGenerationType generatorAnnotation = annotationType.getAnnotation( ValueGenerationType.class ); final ValueGenerationType generatorAnnotation = annotationType.getAnnotation( ValueGenerationType.class );
if ( generatorAnnotation == null ) { if ( generatorAnnotation == null ) {
return null; return null;
} }
checkGeneratorType( generatorAnnotation.generatedBy() );
return creationContext -> { return creationContext -> {
final Generator generator = final Generator generator =
instantiateGenerator( instantiateGenerator(
@ -438,13 +475,27 @@ public class PropertyBinder {
}; };
} }
private static void checkGeneratorType(Class<? extends Generator> generatorClass) {
// we don't yet support the additional "fancy" operations of
// IdentifierGenerator with regular generators, though this
// would be extremely easy to add if anyone asks for it
if ( IdentifierGenerator.class.isAssignableFrom( generatorClass ) ) {
throw new AnnotationException("Generator class '" + generatorClass.getName()
+ "' implements 'IdentifierGenerator' and may not be used with '@ValueGenerationType'");
}
if ( ExportableProducer.class.isAssignableFrom( generatorClass ) ) {
throw new AnnotationException("Generator class '" + generatorClass.getName()
+ "' implements 'ExportableProducer' and may not be used with '@ValueGenerationType'");
}
}
public static IdentifierGeneratorCreator identifierGeneratorCreator(XProperty idProperty, Annotation annotation) { public static IdentifierGeneratorCreator identifierGeneratorCreator(XProperty idProperty, Annotation annotation) {
final Member member = HCANNHelper.getUnderlyingMember( idProperty ); final Member member = HCANNHelper.getUnderlyingMember( idProperty );
final Class<? extends Annotation> annotationType = annotation.annotationType(); final Class<? extends Annotation> annotationType = annotation.annotationType();
final IdGeneratorType idGeneratorType = annotationType.getAnnotation( IdGeneratorType.class ); final IdGeneratorType idGeneratorType = annotationType.getAnnotation( IdGeneratorType.class );
assert idGeneratorType != null; assert idGeneratorType != null;
return creationContext -> { return creationContext -> {
final IdentifierGenerator generator = final InMemoryGenerator generator =
instantiateGenerator( instantiateGenerator(
annotation, annotation,
member, member,
@ -505,11 +556,11 @@ public class PropertyBinder {
} }
} }
private void checkVersionGenerationAlways(XProperty property, Generator generator) { private static void checkVersionGenerationAlways(XProperty property, Generator generator) {
if ( property.isAnnotationPresent(Version.class) ) { if ( property.isAnnotationPresent(Version.class) ) {
final GenerationTiming timing = generator.getGenerationTiming(); final GenerationTiming timing = generator.getGenerationTiming();
if ( !timing.isAlways() ) { if ( !timing.isAlways() ) {
throw new AnnotationException("Property '" + qualify( holder.getPath(), name ) throw new AnnotationException("Property '" + property.getName()
+ "' is annotated '@Version' but has a value generator with timing " + timing.name() + "' is annotated '@Version' but has a value generator with timing " + timing.name()
+ " (the value generation timing must be ALWAYS)" + " (the value generation timing must be ALWAYS)"
); );
@ -517,35 +568,4 @@ public class PropertyBinder {
} }
} }
private boolean isToOneValue(Value value) {
return value instanceof ToOne;
}
public void setProperty(XProperty property) {
this.property = property;
}
public void setReturnedClass(XClass returnedClass) {
this.returnedClass = returnedClass;
}
public BasicValueBinder getBasicValueBinder() {
return basicValueBinder;
}
public Value getValue() {
return value;
}
public void setId(boolean id) {
this.isId = id;
}
public boolean isId() {
return isId;
}
public void setInheritanceStatePerClass(Map<XClass, InheritanceState> inheritanceStatePerClass) {
this.inheritanceStatePerClass = inheritanceStatePerClass;
}
} }

View File

@ -368,7 +368,7 @@ public class PersistentIdentifierBag<E> extends AbstractPersistentCollection<E>
final Integer loc = i++; final Integer loc = i++;
if ( !identifiers.containsKey( loc ) ) { if ( !identifiers.containsKey( loc ) ) {
//TODO: native ids //TODO: native ids
final Object id = persister.getIdentifierGenerator().generate( getSession(), entry ); final Object id = persister.getGenerator().generate( getSession(), entry, null );
identifiers.put( loc, id ); identifiers.put( loc, id );
} }
} }

View File

@ -18,7 +18,6 @@ import org.hibernate.boot.model.relational.QualifiedNameParser;
import org.hibernate.boot.model.relational.QualifiedTableName; import org.hibernate.boot.model.relational.QualifiedTableName;
import org.hibernate.boot.model.relational.SqlStringGenerationContext; import org.hibernate.boot.model.relational.SqlStringGenerationContext;
import org.hibernate.dialect.Dialect; import org.hibernate.dialect.Dialect;
import org.hibernate.id.IdentifierGenerator;
import org.hibernate.id.OptimizableGenerator; import org.hibernate.id.OptimizableGenerator;
import org.hibernate.id.PostInsertIdentifierGenerator; import org.hibernate.id.PostInsertIdentifierGenerator;
import org.hibernate.id.enhanced.Optimizer; import org.hibernate.id.enhanced.Optimizer;
@ -42,6 +41,7 @@ import org.hibernate.metamodel.mapping.PluralAttributeMapping;
import org.hibernate.metamodel.spi.RuntimeModelCreationContext; import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.SingleTableEntityPersister; import org.hibernate.persister.entity.SingleTableEntityPersister;
import org.hibernate.tuple.InMemoryGenerator;
import org.hibernate.type.BasicType; import org.hibernate.type.BasicType;
import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.StandardBasicTypes;
import org.hibernate.type.spi.TypeConfiguration; import org.hibernate.type.spi.TypeConfiguration;
@ -253,8 +253,7 @@ public class TemporaryTable implements Exportable, Contributable {
final PersistentClass entityBinding = runtimeModelCreationContext.getBootModel() final PersistentClass entityBinding = runtimeModelCreationContext.getBootModel()
.getEntityBinding( entityDescriptor.getEntityName() ); .getEntityBinding( entityDescriptor.getEntityName() );
final IdentifierGenerator identifierGenerator = entityDescriptor.getEntityPersister() final InMemoryGenerator identifierGenerator = entityDescriptor.getEntityPersister().getGenerator();
.getIdentifierGenerator();
final boolean identityColumn = identifierGenerator instanceof PostInsertIdentifierGenerator; final boolean identityColumn = identifierGenerator instanceof PostInsertIdentifierGenerator;
final boolean hasOptimizer; final boolean hasOptimizer;
if ( identityColumn ) { if ( identityColumn ) {

View File

@ -46,6 +46,7 @@ import org.hibernate.query.spi.QueryEngine;
import org.hibernate.relational.SchemaManager; import org.hibernate.relational.SchemaManager;
import org.hibernate.service.spi.ServiceRegistryImplementor; import org.hibernate.service.spi.ServiceRegistryImplementor;
import org.hibernate.stat.spi.StatisticsImplementor; import org.hibernate.stat.spi.StatisticsImplementor;
import org.hibernate.tuple.InMemoryGenerator;
import org.hibernate.type.Type; import org.hibernate.type.Type;
import org.hibernate.type.descriptor.WrapperOptions; import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.spi.TypeConfiguration; import org.hibernate.type.spi.TypeConfiguration;
@ -183,6 +184,11 @@ public class SessionFactoryDelegatingImpl implements SessionFactoryImplementor,
return delegate.getIdentifierGenerator( rootEntityName ); return delegate.getIdentifierGenerator( rootEntityName );
} }
@Override
public InMemoryGenerator getGenerator(String rootEntityName) {
return delegate.getGenerator( rootEntityName );
}
@Override @Override
public Map<String, Object> getProperties() { public Map<String, Object> getProperties() {
return delegate.getProperties(); return delegate.getProperties();

View File

@ -33,6 +33,7 @@ import org.hibernate.query.sqm.spi.SqmCreationContext;
import org.hibernate.service.spi.ServiceRegistryImplementor; import org.hibernate.service.spi.ServiceRegistryImplementor;
import org.hibernate.sql.ast.spi.SqlAstCreationContext; import org.hibernate.sql.ast.spi.SqlAstCreationContext;
import org.hibernate.stat.spi.StatisticsImplementor; import org.hibernate.stat.spi.StatisticsImplementor;
import org.hibernate.tuple.InMemoryGenerator;
import org.hibernate.type.descriptor.WrapperOptions; import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.spi.TypeConfiguration; import org.hibernate.type.spi.TypeConfiguration;
@ -120,9 +121,16 @@ public interface SessionFactoryImplementor
/** /**
* Get the identifier generator for the hierarchy * Get the identifier generator for the hierarchy
*
* @deprecated use {@link #getGenerator(String)}
*/ */
@Deprecated(since = "6.2")
IdentifierGenerator getIdentifierGenerator(String rootEntityName); IdentifierGenerator getIdentifierGenerator(String rootEntityName);
/**
* Get the identifier generator for the hierarchy
*/
InMemoryGenerator getGenerator(String rootEntityName);
EntityNotFoundDelegate getEntityNotFoundDelegate(); EntityNotFoundDelegate getEntityNotFoundDelegate();

View File

@ -111,7 +111,7 @@ public abstract class AbstractSaveEventListener<C>
processIfSelfDirtinessTracker( entity, SelfDirtinessTracker::$$_hibernate_clearDirtyAttributes ); processIfSelfDirtinessTracker( entity, SelfDirtinessTracker::$$_hibernate_clearDirtyAttributes );
EntityPersister persister = source.getEntityPersister( entityName, entity ); EntityPersister persister = source.getEntityPersister( entityName, entity );
Object generatedId = persister.getIdentifierGenerator().generate( source, entity ); Object generatedId = persister.getGenerator().generate( source, entity, null );
if ( generatedId == null ) { if ( generatedId == null ) {
throw new IdentifierGenerationException( "null id generated for: " + entity.getClass() ); throw new IdentifierGenerationException( "null id generated for: " + entity.getClass() );
} }
@ -127,7 +127,7 @@ public abstract class AbstractSaveEventListener<C>
LOG.debugf( LOG.debugf(
"Generated identifier: %s, using strategy: %s", "Generated identifier: %s, using strategy: %s",
persister.getIdentifierType().toLoggableString( generatedId, source.getFactory() ), persister.getIdentifierType().toLoggableString( generatedId, source.getFactory() ),
persister.getIdentifierGenerator().getClass().getName() persister.getGenerator().getClass().getName()
); );
} }
return performSave( entity, generatedId, persister, false, context, source, true ); return performSave( entity, generatedId, persister, false, context, source, true );

View File

@ -122,7 +122,7 @@ public class DefaultPersistEventListener
// NOTE: entityEntry must be null to get here, so we cannot use any of its values // NOTE: entityEntry must be null to get here, so we cannot use any of its values
final EntityPersister persister = source.getFactory().getMappingMetamodel() final EntityPersister persister = source.getFactory().getMappingMetamodel()
.getEntityDescriptor( entityName ); .getEntityDescriptor( entityName );
if ( persister.getIdentifierGenerator() instanceof ForeignGenerator ) { if ( persister.getGenerator() instanceof ForeignGenerator ) {
if ( LOG.isDebugEnabled() && persister.getIdentifier( entity, source ) != null ) { if ( LOG.isDebugEnabled() && persister.getIdentifier( entity, source ) != null ) {
LOG.debug( "Resetting entity id attribute to null for foreign generator" ); LOG.debug( "Resetting entity id attribute to null for foreign generator" );
} }

View File

@ -22,18 +22,31 @@ import org.hibernate.type.Type;
import static org.hibernate.tuple.GenerationTiming.INSERT; import static org.hibernate.tuple.GenerationTiming.INSERT;
/** /**
* The general contract between a class that generates unique * A classic extension point from the very earliest days of Hibernate,
* identifiers and the {@link org.hibernate.Session}. It is not * this interface is now no longer the only way to generate identifiers.
* intended that this interface ever be exposed to the application. * Any {@link InMemoryGenerator} may now be used.
* It <em>is</em> intended that users implement this interface to
* provide custom identifier generation strategies.
* <p> * <p>
* Implementors should provide a public default constructor. * This interface extends {@code InMemoryGenerator} with some additional
* machinery for {@linkplain #configure configuration}, and for caching
* {@link #initialize(SqlStringGenerationContext) generated SQL}.
* <p> * <p>
* Implementations that accept configuration parameters should also * Any identifier generator, including a generator which directly implements
* implement {@link Configurable}. * {@code InMemoryGenerator}, may also implement {@link ExportableProducer}.
* For the sake of convenience, {@code PersistentIdentifierGenerator} extends
* {@code ExportableProducer}, in case the implementation needs to export
* objects to the database as part of the process of schema export.
* <p> * <p>
* Implementors <em>must</em> be thread-safe * The {@link #configure(Type, Properties, ServiceRegistry)} method accepts
* a properties object containing named values. These include:
* <ul>
* <li>several "standard" parameters with keys defined as static members of
* this interface: {@value #ENTITY_NAME}, {@value #JPA_ENTITY_NAME},
* {@value #GENERATOR_NAME}, {@value #CONTRIBUTOR_NAME}, along with
* <li>additional parameters supplied by Hibernate to its built-in generators,
* depending on the generator class, and, possibly,
* <li>{@linkplain org.hibernate.annotations.Parameter parameters} specified
* using {@link org.hibernate.annotations.GenericGenerator#parameters()}.
* </ul>
* *
* @author Gavin King * @author Gavin King
* *

View File

@ -0,0 +1,132 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.id.factory.internal;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.config.spi.ConfigurationService;
import org.hibernate.engine.config.spi.StandardConverters;
import org.hibernate.id.IdentifierGenerator;
import org.hibernate.id.OptimizableGenerator;
import org.hibernate.id.PersistentIdentifierGenerator;
import org.hibernate.id.enhanced.LegacyNamingStrategy;
import org.hibernate.id.enhanced.SingleNamingStrategy;
import org.hibernate.id.factory.IdentifierGeneratorFactory;
import org.hibernate.mapping.Column;
import org.hibernate.mapping.RootClass;
import org.hibernate.mapping.SimpleValue;
import org.hibernate.mapping.Table;
import java.util.Properties;
public class IdentifierGeneratorUtil {
public static IdentifierGenerator createLegacyIdentifierGenerator(
SimpleValue simpleValue,
IdentifierGeneratorFactory identifierGeneratorFactory,
Dialect dialect,
String defaultCatalog,
String defaultSchema,
RootClass rootClass) {
final Properties params = new Properties();
// This is for backwards compatibility only;
// when this method is called by Hibernate ORM, defaultSchema and defaultCatalog are always
// null, and defaults are handled later.
if ( defaultSchema != null ) {
params.setProperty( PersistentIdentifierGenerator.SCHEMA, defaultSchema);
}
if ( defaultCatalog != null ) {
params.setProperty( PersistentIdentifierGenerator.CATALOG, defaultCatalog);
}
// default initial value and allocation size per-JPA defaults
params.setProperty( OptimizableGenerator.INITIAL_PARAM, String.valueOf( OptimizableGenerator.DEFAULT_INITIAL_VALUE ) );
final ConfigurationService cs = simpleValue.getMetadata().getMetadataBuildingOptions().getServiceRegistry()
.getService( ConfigurationService.class );
final String idNamingStrategy = cs.getSetting(
AvailableSettings.ID_DB_STRUCTURE_NAMING_STRATEGY,
StandardConverters.STRING,
null
);
if ( LegacyNamingStrategy.STRATEGY_NAME.equals( idNamingStrategy )
|| LegacyNamingStrategy.class.getName().equals( idNamingStrategy )
|| SingleNamingStrategy.STRATEGY_NAME.equals( idNamingStrategy )
|| SingleNamingStrategy.class.getName().equals( idNamingStrategy ) ) {
params.setProperty( OptimizableGenerator.INCREMENT_PARAM, "1" );
}
else {
params.setProperty(
OptimizableGenerator.INCREMENT_PARAM,
String.valueOf( OptimizableGenerator.DEFAULT_INCREMENT_SIZE )
);
}
//init the table here instead of earlier, so that we can get a quoted table name
//TODO: would it be better to simply pass the qualified table name, instead of
// splitting it up into schema/catalog/table names
final String tableName = simpleValue.getTable().getQuotedName(dialect);
params.setProperty( PersistentIdentifierGenerator.TABLE, tableName );
//pass the column name (a generated id almost always has a single column)
final String columnName = ( (Column) simpleValue.getSelectables().get(0) ).getQuotedName(dialect);
params.setProperty( PersistentIdentifierGenerator.PK, columnName );
//pass the entity-name, if not a collection-id
if ( rootClass != null ) {
params.setProperty( IdentifierGenerator.ENTITY_NAME, rootClass.getEntityName() );
params.setProperty( IdentifierGenerator.JPA_ENTITY_NAME, rootClass.getJpaEntityName() );
// The table name is not really a good default for subselect entities, so use the JPA entity name which is short
if ( simpleValue.getTable().isSubselect() ) {
params.setProperty( OptimizableGenerator.IMPLICIT_NAME_BASE, rootClass.getJpaEntityName() );
}
else {
params.setProperty( OptimizableGenerator.IMPLICIT_NAME_BASE, simpleValue.getTable().getName() );
}
final StringBuilder tables = new StringBuilder();
for ( Table table : rootClass.getIdentityTables() ) {
tables.append( table.getQuotedName(dialect) );
if ( tables.length()>0 ) {
tables.append( ", " );
}
}
params.setProperty( PersistentIdentifierGenerator.TABLES, tables.toString() );
}
else {
params.setProperty( PersistentIdentifierGenerator.TABLES, tableName );
params.setProperty( OptimizableGenerator.IMPLICIT_NAME_BASE, tableName );
}
if ( simpleValue.getIdentifierGeneratorParameters() != null ) {
params.putAll( simpleValue.getIdentifierGeneratorParameters() );
}
// TODO : we should pass along all settings once "config lifecycle" is hashed out...
params.put(
IdentifierGenerator.CONTRIBUTOR_NAME,
simpleValue.getBuildingContext().getCurrentContributorName()
);
if ( cs.getSettings().get( AvailableSettings.PREFERRED_POOLED_OPTIMIZER ) != null ) {
params.put(
AvailableSettings.PREFERRED_POOLED_OPTIMIZER,
cs.getSettings().get( AvailableSettings.PREFERRED_POOLED_OPTIMIZER )
);
}
return identifierGeneratorFactory.createIdentifierGenerator(
simpleValue.getIdentifierGeneratorStrategy(),
simpleValue.getType(),
params
);
}
}

View File

@ -52,7 +52,7 @@ import org.hibernate.type.descriptor.java.JavaType;
import static org.hibernate.id.factory.IdGenFactoryLogging.ID_GEN_FAC_LOGGER; import static org.hibernate.id.factory.IdGenFactoryLogging.ID_GEN_FAC_LOGGER;
/** /**
* Basic {@code templated} support for {@link org.hibernate.id.factory.IdentifierGeneratorFactory} implementations. * Basic implementation of {@link org.hibernate.id.factory.IdentifierGeneratorFactory}.
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */

View File

@ -124,6 +124,7 @@ import org.hibernate.service.spi.SessionFactoryServiceRegistryFactory;
import org.hibernate.stat.spi.StatisticsImplementor; import org.hibernate.stat.spi.StatisticsImplementor;
import org.hibernate.tool.schema.spi.DelayedDropAction; import org.hibernate.tool.schema.spi.DelayedDropAction;
import org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator; import org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator;
import org.hibernate.tuple.InMemoryGenerator;
import org.hibernate.type.Type; import org.hibernate.type.Type;
import org.hibernate.type.descriptor.WrapperOptions; import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.spi.TypeConfiguration; import org.hibernate.type.spi.TypeConfiguration;
@ -183,7 +184,7 @@ public class SessionFactoryImpl implements SessionFactoryImplementor {
private volatile DelayedDropAction delayedDropAction; private volatile DelayedDropAction delayedDropAction;
// todo : move to MetamodelImpl // todo : move to MetamodelImpl
private final transient Map<String,IdentifierGenerator> identifierGenerators; private final transient Map<String, InMemoryGenerator> identifierGenerators;
private final transient Map<String, FilterDefinition> filters; private final transient Map<String, FilterDefinition> filters;
private final transient Map<String, FetchProfile> fetchProfiles; private final transient Map<String, FetchProfile> fetchProfiles;
@ -293,12 +294,14 @@ public class SessionFactoryImpl implements SessionFactoryImplementor {
//Generators: //Generators:
this.identifierGenerators = new HashMap<>(); this.identifierGenerators = new HashMap<>();
bootMetamodel.getEntityBindings().stream().filter( model -> !model.isInherited() ).forEach( model -> { bootMetamodel.getEntityBindings().stream().filter( model -> !model.isInherited() ).forEach( model -> {
final IdentifierGenerator generator = model.getIdentifier().createIdentifierGenerator( final InMemoryGenerator generator = model.getIdentifier().createGenerator(
bootstrapContext.getIdentifierGeneratorFactory(), bootstrapContext.getIdentifierGeneratorFactory(),
jdbcServices.getJdbcEnvironment().getDialect(), jdbcServices.getJdbcEnvironment().getDialect(),
(RootClass) model (RootClass) model
); );
generator.initialize( sqlStringGenerationContext ); if ( generator instanceof IdentifierGenerator ) {
( (IdentifierGenerator) generator ).initialize( sqlStringGenerationContext );
}
identifierGenerators.put( model.getEntityName(), generator ); identifierGenerators.put( model.getEntityName(), generator );
} ); } );
bootMetamodel.validate(); bootMetamodel.validate();
@ -985,8 +988,14 @@ public class SessionFactoryImpl implements SessionFactoryImplementor {
return unmodifiableSet( fetchProfiles.keySet() ); return unmodifiableSet( fetchProfiles.keySet() );
} }
@Deprecated
public IdentifierGenerator getIdentifierGenerator(String rootEntityName) { public IdentifierGenerator getIdentifierGenerator(String rootEntityName) {
return identifierGenerators.get(rootEntityName); return (IdentifierGenerator) getGenerator( rootEntityName );
}
@Deprecated
public InMemoryGenerator getGenerator(String rootEntityName) {
return identifierGenerators.get( rootEntityName );
} }
private boolean canAccessTransactionManager() { private boolean canAccessTransactionManager() {

View File

@ -93,7 +93,7 @@ public class StatelessSessionImpl extends AbstractSharedSessionContract implemen
public Object insert(String entityName, Object entity) { public Object insert(String entityName, Object entity) {
checkOpen(); checkOpen();
EntityPersister persister = getEntityPersister( entityName, entity ); EntityPersister persister = getEntityPersister( entityName, entity );
Object id = persister.getIdentifierGenerator().generate( this, entity ); Object id = persister.getGenerator().generate( this, entity, null );
Object[] state = persister.getValues( entity ); Object[] state = persister.getValues( entity );
if ( persister.isVersioned() ) { if ( persister.isVersioned() ) {
boolean substitute = Versioning.seedVersion( boolean substitute = Versioning.seedVersion(

View File

@ -18,6 +18,7 @@ import java.util.stream.Collectors;
import org.hibernate.MappingException; import org.hibernate.MappingException;
import org.hibernate.Remove; import org.hibernate.Remove;
import org.hibernate.boot.model.relational.Database; import org.hibernate.boot.model.relational.Database;
import org.hibernate.boot.model.relational.ExportableProducer;
import org.hibernate.boot.model.relational.SqlStringGenerationContext; import org.hibernate.boot.model.relational.SqlStringGenerationContext;
import org.hibernate.boot.model.source.internal.hbm.MappingDocument; import org.hibernate.boot.model.source.internal.hbm.MappingDocument;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
@ -33,6 +34,7 @@ import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.internal.util.collections.JoinedIterator; import org.hibernate.internal.util.collections.JoinedIterator;
import org.hibernate.metamodel.spi.EmbeddableInstantiator; import org.hibernate.metamodel.spi.EmbeddableInstantiator;
import org.hibernate.property.access.spi.Setter; import org.hibernate.property.access.spi.Setter;
import org.hibernate.tuple.InMemoryGenerator;
import org.hibernate.type.ComponentType; import org.hibernate.type.ComponentType;
import org.hibernate.type.EmbeddedComponentType; import org.hibernate.type.EmbeddedComponentType;
import org.hibernate.type.Type; import org.hibernate.type.Type;
@ -70,7 +72,7 @@ public class Component extends SimpleValue implements MetaAttributable, Sortable
// lazily computed based on 'properties' field: invalidate by setting to null when properties are modified // lazily computed based on 'properties' field: invalidate by setting to null when properties are modified
private transient List<Column> cachedColumns; private transient List<Column> cachedColumns;
private transient IdentifierGenerator builtIdentifierGenerator; private transient InMemoryGenerator builtIdentifierGenerator;
public Component(MetadataBuildingContext metadata, PersistentClass owner) throws MappingException { public Component(MetadataBuildingContext metadata, PersistentClass owner) throws MappingException {
this( metadata, owner.getTable(), owner ); this( metadata, owner.getTable(), owner );
@ -412,34 +414,30 @@ public class Component extends SimpleValue implements MetaAttributable, Sortable
} }
@Override @Override
public IdentifierGenerator createIdentifierGenerator( public InMemoryGenerator createGenerator(
IdentifierGeneratorFactory identifierGeneratorFactory, IdentifierGeneratorFactory identifierGeneratorFactory,
Dialect dialect, Dialect dialect,
String defaultCatalog,
String defaultSchema,
RootClass rootClass) throws MappingException { RootClass rootClass) throws MappingException {
if ( builtIdentifierGenerator == null ) { if ( builtIdentifierGenerator == null ) {
builtIdentifierGenerator = buildIdentifierGenerator( builtIdentifierGenerator = buildIdentifierGenerator(
identifierGeneratorFactory, identifierGeneratorFactory,
dialect, dialect,
defaultCatalog,
defaultSchema,
rootClass rootClass
); );
} }
return builtIdentifierGenerator; return builtIdentifierGenerator;
} }
private IdentifierGenerator buildIdentifierGenerator( private InMemoryGenerator buildIdentifierGenerator(
IdentifierGeneratorFactory identifierGeneratorFactory, IdentifierGeneratorFactory identifierGeneratorFactory,
Dialect dialect, Dialect dialect,
String defaultCatalog,
String defaultSchema,
RootClass rootClass) throws MappingException { RootClass rootClass) throws MappingException {
final boolean hasCustomGenerator = ! DEFAULT_ID_GEN_STRATEGY.equals( getIdentifierGeneratorStrategy() ); final boolean hasCustomGenerator = ! DEFAULT_ID_GEN_STRATEGY.equals( getIdentifierGeneratorStrategy() );
if ( hasCustomGenerator ) { if ( hasCustomGenerator ) {
return super.createIdentifierGenerator( return super.createGenerator(
identifierGeneratorFactory, dialect, defaultCatalog, defaultSchema, rootClass identifierGeneratorFactory,
dialect,
rootClass
); );
} }
@ -469,25 +467,16 @@ public class Component extends SimpleValue implements MetaAttributable, Sortable
if ( property.getValue().isSimpleValue() ) { if ( property.getValue().isSimpleValue() ) {
final SimpleValue value = (SimpleValue) property.getValue(); final SimpleValue value = (SimpleValue) property.getValue();
if ( DEFAULT_ID_GEN_STRATEGY.equals( value.getIdentifierGeneratorStrategy() ) ) { if ( !DEFAULT_ID_GEN_STRATEGY.equals( value.getIdentifierGeneratorStrategy() ) ) {
// skip any 'assigned' generators, they would have been handled by // skip any 'assigned' generators, they would have been handled by
// the StandardGenerationContextLocator // the StandardGenerationContextLocator
continue; generator.addGeneratedValuePlan(
new ValueGenerationPlan(
value.createGenerator( identifierGeneratorFactory, dialect, rootClass ),
injector( property, attributeDeclarer )
)
);
} }
final IdentifierGenerator valueGenerator = value.createIdentifierGenerator(
identifierGeneratorFactory,
dialect,
defaultCatalog,
defaultSchema,
rootClass
);
generator.addGeneratedValuePlan(
new ValueGenerationPlan(
valueGenerator,
injector( property, attributeDeclarer )
)
);
} }
} }
return generator; return generator;
@ -523,11 +512,11 @@ public class Component extends SimpleValue implements MetaAttributable, Sortable
} }
public static class ValueGenerationPlan implements CompositeNestedGeneratedValueGenerator.GenerationPlan { public static class ValueGenerationPlan implements CompositeNestedGeneratedValueGenerator.GenerationPlan {
private final IdentifierGenerator subGenerator; private final InMemoryGenerator subGenerator;
private final Setter injector; private final Setter injector;
public ValueGenerationPlan( public ValueGenerationPlan(
IdentifierGenerator subGenerator, InMemoryGenerator subGenerator,
Setter injector) { Setter injector) {
this.subGenerator = subGenerator; this.subGenerator = subGenerator;
this.injector = injector; this.injector = injector;
@ -535,18 +524,21 @@ public class Component extends SimpleValue implements MetaAttributable, Sortable
@Override @Override
public void execute(SharedSessionContractImplementor session, Object incomingObject, Object injectionContext) { public void execute(SharedSessionContractImplementor session, Object incomingObject, Object injectionContext) {
final Object generatedValue = subGenerator.generate( session, incomingObject ); injector.set( injectionContext, subGenerator.generate( session, incomingObject, null ) );
injector.set( injectionContext, generatedValue );
} }
@Override @Override
public void registerExportables(Database database) { public void registerExportables(Database database) {
subGenerator.registerExportables( database ); if ( subGenerator instanceof ExportableProducer ) {
( (ExportableProducer) subGenerator ).registerExportables( database );
}
} }
@Override @Override
public void initialize(SqlStringGenerationContext context) { public void initialize(SqlStringGenerationContext context) {
subGenerator.initialize( context ); if ( subGenerator instanceof IdentifierGenerator ) {
( (IdentifierGenerator) subGenerator ).initialize( context );
}
} }
} }

View File

@ -6,10 +6,10 @@
*/ */
package org.hibernate.mapping; package org.hibernate.mapping;
import org.hibernate.id.IdentifierGenerator;
import org.hibernate.id.factory.spi.CustomIdGeneratorCreationContext; import org.hibernate.id.factory.spi.CustomIdGeneratorCreationContext;
import org.hibernate.tuple.InMemoryGenerator;
@FunctionalInterface @FunctionalInterface
public interface IdentifierGeneratorCreator { public interface IdentifierGeneratorCreator {
IdentifierGenerator createGenerator(CustomIdGeneratorCreationContext context); InMemoryGenerator createGenerator(CustomIdGeneratorCreationContext context);
} }

View File

@ -6,10 +6,10 @@
*/ */
package org.hibernate.mapping; package org.hibernate.mapping;
import org.hibernate.MappingException;
import org.hibernate.dialect.Dialect; import org.hibernate.dialect.Dialect;
import org.hibernate.id.IdentifierGenerator; import org.hibernate.id.IdentifierGenerator;
import org.hibernate.id.factory.IdentifierGeneratorFactory; import org.hibernate.id.factory.IdentifierGeneratorFactory;
import org.hibernate.tuple.InMemoryGenerator;
/** /**
* A mapping model {@link Value} which may be treated as an identifying key of a * A mapping model {@link Value} which may be treated as an identifying key of a
@ -21,23 +21,6 @@ import org.hibernate.id.factory.IdentifierGeneratorFactory;
*/ */
public interface KeyValue extends Value { public interface KeyValue extends Value {
/**
* @deprecated Use {@link #createIdentifierGenerator(IdentifierGeneratorFactory, Dialect, RootClass)}
* instead.
*/
@Deprecated
IdentifierGenerator createIdentifierGenerator(
IdentifierGeneratorFactory identifierGeneratorFactory,
Dialect dialect,
String defaultCatalog,
String defaultSchema,
RootClass rootClass) throws MappingException;
IdentifierGenerator createIdentifierGenerator(
IdentifierGeneratorFactory identifierGeneratorFactory,
Dialect dialect,
RootClass rootClass) throws MappingException;
boolean isIdentityColumn(IdentifierGeneratorFactory identifierGeneratorFactory, Dialect dialect); boolean isIdentityColumn(IdentifierGeneratorFactory identifierGeneratorFactory, Dialect dialect);
ForeignKey createForeignKeyOfEntity(String entityName); ForeignKey createForeignKeyOfEntity(String entityName);
@ -47,4 +30,34 @@ public interface KeyValue extends Value {
String getNullValue(); String getNullValue();
boolean isUpdateable(); boolean isUpdateable();
InMemoryGenerator createGenerator(
IdentifierGeneratorFactory identifierGeneratorFactory,
Dialect dialect,
RootClass rootClass);
/**
* @deprecated Use {@link #createGenerator(IdentifierGeneratorFactory, Dialect, RootClass)} instead.
*/
@Deprecated
default IdentifierGenerator createIdentifierGenerator(
IdentifierGeneratorFactory identifierGeneratorFactory,
Dialect dialect,
String defaultCatalog,
String defaultSchema,
RootClass rootClass) {
return (IdentifierGenerator) createGenerator( identifierGeneratorFactory, dialect, rootClass );
}
/**
* @deprecated Use {@link #createGenerator(IdentifierGeneratorFactory, Dialect, RootClass)} instead.
*/
@Deprecated
default IdentifierGenerator createIdentifierGenerator(
IdentifierGeneratorFactory identifierGeneratorFactory,
Dialect dialect,
RootClass rootClass) {
return (IdentifierGenerator) createGenerator( identifierGeneratorFactory, dialect, rootClass );
}
} }

View File

@ -34,17 +34,10 @@ import org.hibernate.boot.registry.classloading.spi.ClassLoadingException;
import org.hibernate.boot.spi.InFlightMetadataCollector; import org.hibernate.boot.spi.InFlightMetadataCollector;
import org.hibernate.boot.spi.MetadataBuildingContext; import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.boot.spi.MetadataImplementor; import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.dialect.Dialect; import org.hibernate.dialect.Dialect;
import org.hibernate.engine.config.spi.ConfigurationService;
import org.hibernate.engine.config.spi.StandardConverters;
import org.hibernate.engine.spi.Mapping; import org.hibernate.engine.spi.Mapping;
import org.hibernate.id.IdentifierGenerator; import org.hibernate.id.IdentifierGenerator;
import org.hibernate.id.IdentityGenerator; import org.hibernate.id.IdentityGenerator;
import org.hibernate.id.OptimizableGenerator;
import org.hibernate.id.PersistentIdentifierGenerator;
import org.hibernate.id.enhanced.LegacyNamingStrategy;
import org.hibernate.id.enhanced.SingleNamingStrategy;
import org.hibernate.id.factory.IdentifierGeneratorFactory; import org.hibernate.id.factory.IdentifierGeneratorFactory;
import org.hibernate.id.factory.spi.CustomIdGeneratorCreationContext; import org.hibernate.id.factory.spi.CustomIdGeneratorCreationContext;
import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreLogging;
@ -54,6 +47,7 @@ import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.metamodel.model.convert.spi.JpaAttributeConverter; import org.hibernate.metamodel.model.convert.spi.JpaAttributeConverter;
import org.hibernate.resource.beans.spi.ManagedBeanRegistry; import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistry;
import org.hibernate.tuple.InMemoryGenerator;
import org.hibernate.type.Type; import org.hibernate.type.Type;
import org.hibernate.type.descriptor.JdbcTypeNameMapper; import org.hibernate.type.descriptor.JdbcTypeNameMapper;
import org.hibernate.type.descriptor.java.JavaType; import org.hibernate.type.descriptor.java.JavaType;
@ -67,6 +61,8 @@ import org.hibernate.usertype.DynamicParameterizedType;
import jakarta.persistence.AttributeConverter; import jakarta.persistence.AttributeConverter;
import static org.hibernate.id.factory.internal.IdentifierGeneratorUtil.createLegacyIdentifierGenerator;
/** /**
* A mapping model object that represents any value that maps to columns. * A mapping model object that represents any value that maps to columns.
* *
@ -104,6 +100,10 @@ public abstract class SimpleValue implements KeyValue {
private ConverterDescriptor attributeConverterDescriptor; private ConverterDescriptor attributeConverterDescriptor;
private Type type; private Type type;
private IdentifierGeneratorCreator customIdGeneratorCreator;
private GeneratorCreator customGeneratorCreator;
private InMemoryGenerator generator;
public SimpleValue(MetadataBuildingContext buildingContext) { public SimpleValue(MetadataBuildingContext buildingContext) {
this.buildingContext = buildingContext; this.buildingContext = buildingContext;
this.metadata = buildingContext.getMetadataCollector(); this.metadata = buildingContext.getMetadataCollector();
@ -136,7 +136,7 @@ public abstract class SimpleValue implements KeyValue {
this.attributeConverterDescriptor = original.attributeConverterDescriptor; this.attributeConverterDescriptor = original.attributeConverterDescriptor;
this.type = original.type; this.type = original.type;
this.customIdGeneratorCreator = original.customIdGeneratorCreator; this.customIdGeneratorCreator = original.customIdGeneratorCreator;
this.identifierGenerator = original.identifierGenerator; this.generator = original.generator;
} }
public MetadataBuildingContext getBuildingContext() { public MetadataBuildingContext getBuildingContext() {
@ -359,9 +359,6 @@ public abstract class SimpleValue implements KeyValue {
getTable().createUniqueKey( getConstraintColumns() ); getTable().createUniqueKey( getConstraintColumns() );
} }
private IdentifierGeneratorCreator customIdGeneratorCreator;
private IdentifierGenerator identifierGenerator;
/** /**
* Returns the cached {@link IdentifierGenerator}, or null if * Returns the cached {@link IdentifierGenerator}, or null if
* {@link #createIdentifierGenerator(IdentifierGeneratorFactory, Dialect, String, String, RootClass)} * {@link #createIdentifierGenerator(IdentifierGeneratorFactory, Dialect, String, String, RootClass)}
@ -371,7 +368,7 @@ public abstract class SimpleValue implements KeyValue {
*/ */
@Deprecated(since = "6.0") @Deprecated(since = "6.0")
public IdentifierGenerator getIdentifierGenerator() { public IdentifierGenerator getIdentifierGenerator() {
return identifierGenerator; return (IdentifierGenerator) generator;
} }
public void setCustomIdGeneratorCreator(IdentifierGeneratorCreator customIdGeneratorCreator) { public void setCustomIdGeneratorCreator(IdentifierGeneratorCreator customIdGeneratorCreator) {
@ -382,171 +379,41 @@ public abstract class SimpleValue implements KeyValue {
return customIdGeneratorCreator; return customIdGeneratorCreator;
} }
@Override public GeneratorCreator getCustomGeneratorCreator() {
public IdentifierGenerator createIdentifierGenerator( return customGeneratorCreator;
IdentifierGeneratorFactory identifierGeneratorFactory, }
Dialect dialect,
RootClass rootClass) throws MappingException { public void setCustomGeneratorCreator(GeneratorCreator customGeneratorCreator) {
return createIdentifierGenerator( identifierGeneratorFactory, dialect, null, null, rootClass ); this.customGeneratorCreator = customGeneratorCreator;
} }
@Override @Override
public IdentifierGenerator createIdentifierGenerator( public InMemoryGenerator createGenerator(
IdentifierGeneratorFactory identifierGeneratorFactory, IdentifierGeneratorFactory identifierGeneratorFactory,
Dialect dialect, Dialect dialect,
String defaultCatalog,
String defaultSchema,
RootClass rootClass) throws MappingException { RootClass rootClass) throws MappingException {
if ( identifierGenerator != null ) { if ( generator != null ) {
return identifierGenerator; return generator;
} }
if ( customIdGeneratorCreator != null ) { if ( customIdGeneratorCreator != null ) {
final CustomIdGeneratorCreationContext creationContext = new CustomIdGeneratorCreationContext() { generator = customIdGeneratorCreator.createGenerator(
@Override new IdGeneratorCreationContext( identifierGeneratorFactory, null, null, rootClass )
public IdentifierGeneratorFactory getIdentifierGeneratorFactory() {
return identifierGeneratorFactory;
}
@Override
public Database getDatabase() {
return buildingContext.getMetadataCollector().getDatabase();
}
@Override
public ServiceRegistry getServiceRegistry() {
return buildingContext.getBootstrapContext().getServiceRegistry();
}
@Override
public String getDefaultCatalog() {
return defaultCatalog;
}
@Override
public String getDefaultSchema() {
return defaultSchema;
}
@Override
public RootClass getRootClass() {
return rootClass;
}
@Override
public PersistentClass getPersistentClass() {
return rootClass;
}
@Override
public Property getProperty() {
return rootClass.getIdentifierProperty();
}
};
identifierGenerator = customIdGeneratorCreator.createGenerator( creationContext );
return identifierGenerator;
}
final Properties params = new Properties();
// This is for backwards compatibility only;
// when this method is called by Hibernate ORM, defaultSchema and defaultCatalog are always
// null, and defaults are handled later.
if ( defaultSchema != null ) {
params.setProperty( PersistentIdentifierGenerator.SCHEMA, defaultSchema);
}
if ( defaultCatalog != null ) {
params.setProperty( PersistentIdentifierGenerator.CATALOG, defaultCatalog );
}
// default initial value and allocation size per-JPA defaults
params.setProperty( OptimizableGenerator.INITIAL_PARAM, String.valueOf( OptimizableGenerator.DEFAULT_INITIAL_VALUE ) );
final ConfigurationService cs = metadata.getMetadataBuildingOptions().getServiceRegistry()
.getService( ConfigurationService.class );
final String idNamingStrategy = cs.getSetting(
AvailableSettings.ID_DB_STRUCTURE_NAMING_STRATEGY,
StandardConverters.STRING,
null
);
if ( LegacyNamingStrategy.STRATEGY_NAME.equals( idNamingStrategy )
|| LegacyNamingStrategy.class.getName().equals( idNamingStrategy )
|| SingleNamingStrategy.STRATEGY_NAME.equals( idNamingStrategy )
|| SingleNamingStrategy.class.getName().equals( idNamingStrategy ) ) {
params.setProperty( OptimizableGenerator.INCREMENT_PARAM, "1" );
}
else {
params.setProperty(
OptimizableGenerator.INCREMENT_PARAM,
String.valueOf( OptimizableGenerator.DEFAULT_INCREMENT_SIZE )
); );
return generator;
} }
//init the table here instead of earlier, so that we can get a quoted table name else if ( customGeneratorCreator != null ) {
//TODO: would it be better to simply pass the qualified table name, instead of // we may as well allow this, so you don't have to annotate generator
// splitting it up into schema/catalog/table names // annotations twice, with @IdGeneratorType and @ValueGenerationType
final String tableName = getTable().getQuotedName( dialect ); //TODO: this typecast is ugly ... throw a better exception at least
params.setProperty( PersistentIdentifierGenerator.TABLE, tableName ); generator = (InMemoryGenerator) customGeneratorCreator.createGenerator(
new IdGeneratorCreationContext( identifierGeneratorFactory, null, null, rootClass )
//pass the column name (a generated id almost always has a single column)
final String columnName = ( (Column) getSelectables().get(0) ).getQuotedName( dialect );
params.setProperty( PersistentIdentifierGenerator.PK, columnName );
//pass the entity-name, if not a collection-id
if ( rootClass != null ) {
params.setProperty( IdentifierGenerator.ENTITY_NAME, rootClass.getEntityName() );
params.setProperty( IdentifierGenerator.JPA_ENTITY_NAME, rootClass.getJpaEntityName() );
// The table name is not really a good default for subselect entities, so use the JPA entity name which is short
if ( getTable().isSubselect() ) {
params.setProperty( OptimizableGenerator.IMPLICIT_NAME_BASE, rootClass.getJpaEntityName() );
}
else {
params.setProperty( OptimizableGenerator.IMPLICIT_NAME_BASE, getTable().getName() );
}
final StringBuilder tables = new StringBuilder();
final Iterator<Table> itr = rootClass.getIdentityTables().iterator();
while ( itr.hasNext() ) {
final Table table = itr.next();
tables.append( table.getQuotedName( dialect ) );
if ( itr.hasNext() ) {
tables.append( ", " );
}
}
params.setProperty( PersistentIdentifierGenerator.TABLES, tables.toString() );
}
else {
params.setProperty( PersistentIdentifierGenerator.TABLES, tableName );
params.setProperty( OptimizableGenerator.IMPLICIT_NAME_BASE, tableName );
}
if ( identifierGeneratorParameters != null ) {
params.putAll(identifierGeneratorParameters);
}
// TODO : we should pass along all settings once "config lifecycle" is hashed out...
params.put(
IdentifierGenerator.CONTRIBUTOR_NAME,
buildingContext.getCurrentContributorName()
);
if ( cs.getSettings().get( AvailableSettings.PREFERRED_POOLED_OPTIMIZER ) != null ) {
params.put(
AvailableSettings.PREFERRED_POOLED_OPTIMIZER,
cs.getSettings().get( AvailableSettings.PREFERRED_POOLED_OPTIMIZER )
); );
return generator;
} }
identifierGenerator = identifierGeneratorFactory.createIdentifierGenerator( generator = createLegacyIdentifierGenerator(this, identifierGeneratorFactory, dialect, null, null, rootClass );
identifierGeneratorStrategy, return generator;
getType(),
params
);
return identifierGenerator;
} }
public boolean isUpdateable() { public boolean isUpdateable() {
@ -1185,4 +1052,58 @@ public abstract class SimpleValue implements KeyValue {
return columnLengths; return columnLengths;
} }
} }
private class IdGeneratorCreationContext implements CustomIdGeneratorCreationContext {
private final IdentifierGeneratorFactory identifierGeneratorFactory;
private final String defaultCatalog;
private final String defaultSchema;
private final RootClass rootClass;
public IdGeneratorCreationContext(IdentifierGeneratorFactory identifierGeneratorFactory, String defaultCatalog, String defaultSchema, RootClass rootClass) {
this.identifierGeneratorFactory = identifierGeneratorFactory;
this.defaultCatalog = defaultCatalog;
this.defaultSchema = defaultSchema;
this.rootClass = rootClass;
}
@Override
public IdentifierGeneratorFactory getIdentifierGeneratorFactory() {
return identifierGeneratorFactory;
}
@Override
public Database getDatabase() {
return buildingContext.getMetadataCollector().getDatabase();
}
@Override
public ServiceRegistry getServiceRegistry() {
return buildingContext.getBootstrapContext().getServiceRegistry();
}
@Override
public String getDefaultCatalog() {
return defaultCatalog;
}
@Override
public String getDefaultSchema() {
return defaultSchema;
}
@Override
public RootClass getRootClass() {
return rootClass;
}
@Override
public PersistentClass getPersistentClass() {
return rootClass;
}
@Override
public Property getProperty() {
return rootClass.getIdentifierProperty();
}
}
} }

View File

@ -128,6 +128,7 @@ import org.hibernate.sql.model.jdbc.JdbcDeleteMutation;
import org.hibernate.sql.model.jdbc.JdbcMutationOperation; import org.hibernate.sql.model.jdbc.JdbcMutationOperation;
import org.hibernate.sql.results.graph.DomainResult; import org.hibernate.sql.results.graph.DomainResult;
import org.hibernate.sql.results.internal.SqlSelectionImpl; import org.hibernate.sql.results.internal.SqlSelectionImpl;
import org.hibernate.tuple.InMemoryGenerator;
import org.hibernate.type.CollectionType; import org.hibernate.type.CollectionType;
import org.hibernate.type.CompositeType; import org.hibernate.type.CompositeType;
import org.hibernate.type.EntityType; import org.hibernate.type.EntityType;
@ -225,7 +226,7 @@ public abstract class AbstractCollectionPersister
protected final SqlExceptionHelper sqlExceptionHelper; protected final SqlExceptionHelper sqlExceptionHelper;
private final SessionFactoryImplementor factory; private final SessionFactoryImplementor factory;
private final EntityPersister ownerPersister; private final EntityPersister ownerPersister;
private final IdentifierGenerator identifierGenerator; private final InMemoryGenerator identifierGenerator;
private final PropertyMapping elementPropertyMapping; private final PropertyMapping elementPropertyMapping;
private final EntityPersister elementPersister; private final EntityPersister elementPersister;
private final CollectionDataAccess cacheAccessStrategy; private final CollectionDataAccess cacheAccessStrategy;
@ -509,12 +510,14 @@ public abstract class AbstractCollectionPersister
Column col = idColl.getIdentifier().getColumns().get(0); Column col = idColl.getIdentifier().getColumns().get(0);
identifierColumnName = col.getQuotedName( dialect ); identifierColumnName = col.getQuotedName( dialect );
identifierColumnAlias = col.getAlias( dialect ); identifierColumnAlias = col.getAlias( dialect );
identifierGenerator = idColl.getIdentifier().createIdentifierGenerator( identifierGenerator = idColl.getIdentifier().createGenerator(
creationContext.getBootstrapContext().getIdentifierGeneratorFactory(), creationContext.getBootstrapContext().getIdentifierGeneratorFactory(),
factory.getJdbcServices().getDialect(), factory.getJdbcServices().getDialect(),
null null
); );
identifierGenerator.initialize( creationContext.getSessionFactory().getSqlStringGenerationContext() ); if ( identifierGenerator instanceof IdentifierGenerator ) {
( (IdentifierGenerator) identifierGenerator ).initialize( creationContext.getSessionFactory().getSqlStringGenerationContext() );
}
} }
else { else {
identifierType = null; identifierType = null;
@ -1139,8 +1142,13 @@ public abstract class AbstractCollectionPersister
return ownerPersister; return ownerPersister;
} }
@Override @Override @Deprecated
public IdentifierGenerator getIdentifierGenerator() { public IdentifierGenerator getIdentifierGenerator() {
return (IdentifierGenerator) identifierGenerator;
}
@Override
public InMemoryGenerator getGenerator() {
return identifierGenerator; return identifierGenerator;
} }

View File

@ -33,6 +33,7 @@ import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.sql.ast.spi.SqlAstCreationState; import org.hibernate.sql.ast.spi.SqlAstCreationState;
import org.hibernate.sql.ast.tree.from.TableGroup; import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.ast.tree.predicate.Predicate; import org.hibernate.sql.ast.tree.predicate.Predicate;
import org.hibernate.tuple.InMemoryGenerator;
import org.hibernate.type.CollectionType; import org.hibernate.type.CollectionType;
import org.hibernate.type.Type; import org.hibernate.type.Type;
@ -231,9 +232,19 @@ public interface CollectionPersister extends Restrictable {
/** /**
* Get the surrogate key generation strategy (optional operation) * Get the surrogate key generation strategy (optional operation)
*
* @deprecated use {@link #getGenerator()}
*/ */
@Deprecated
IdentifierGenerator getIdentifierGenerator(); IdentifierGenerator getIdentifierGenerator();
/**
* Get the surrogate key generation strategy (optional operation)
*/
default InMemoryGenerator getGenerator() {
return getIdentifierGenerator();
}
/** /**
* Get the type of the surrogate key * Get the type of the surrogate key
*/ */

View File

@ -259,6 +259,7 @@ import org.hibernate.stat.spi.StatisticsImplementor;
import org.hibernate.tuple.Generator; import org.hibernate.tuple.Generator;
import org.hibernate.tuple.InDatabaseGenerator; import org.hibernate.tuple.InDatabaseGenerator;
import org.hibernate.tuple.GenerationTiming; import org.hibernate.tuple.GenerationTiming;
import org.hibernate.tuple.InMemoryGenerator;
import org.hibernate.tuple.NonIdentifierAttribute; import org.hibernate.tuple.NonIdentifierAttribute;
import org.hibernate.tuple.entity.EntityBasedAssociationAttribute; import org.hibernate.tuple.entity.EntityBasedAssociationAttribute;
import org.hibernate.tuple.entity.EntityMetamodel; import org.hibernate.tuple.entity.EntityMetamodel;
@ -3936,11 +3937,16 @@ public abstract class AbstractEntityPersister
return entityMetamodel.isLazy() && !entityMetamodel.getBytecodeEnhancementMetadata().isEnhancedForLazyLoading(); return entityMetamodel.isLazy() && !entityMetamodel.getBytecodeEnhancementMetadata().isEnhancedForLazyLoading();
} }
@Override @Override @Deprecated
public IdentifierGenerator getIdentifierGenerator() throws HibernateException { public IdentifierGenerator getIdentifierGenerator() throws HibernateException {
return entityMetamodel.getIdentifierProperty().getIdentifierGenerator(); return entityMetamodel.getIdentifierProperty().getIdentifierGenerator();
} }
@Override
public InMemoryGenerator getGenerator() {
return entityMetamodel.getIdentifierProperty().getGenerator();
}
@Override @Override
public String getRootEntityName() { public String getRootEntityName() {
return entityMetamodel.getRootName(); return entityMetamodel.getRootName();
@ -4821,9 +4827,9 @@ public abstract class AbstractEntityPersister
sqmMultiTableMutationStrategy = null; sqmMultiTableMutationStrategy = null;
} }
if ( !needsMultiTableInsert && getIdentifierGenerator() instanceof BulkInsertionCapableIdentifierGenerator ) { if ( !needsMultiTableInsert && getGenerator() instanceof BulkInsertionCapableIdentifierGenerator ) {
if ( getIdentifierGenerator() instanceof OptimizableGenerator ) { if ( getGenerator() instanceof OptimizableGenerator ) {
final Optimizer optimizer = ( (OptimizableGenerator) getIdentifierGenerator() ).getOptimizer(); final Optimizer optimizer = ( (OptimizableGenerator) getGenerator() ).getOptimizer();
needsMultiTableInsert = optimizer != null && optimizer.getIncrementSize() > 1; needsMultiTableInsert = optimizer != null && optimizer.getIncrementSize() > 1;
} }
} }

View File

@ -44,6 +44,7 @@ import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
import org.hibernate.sql.ast.spi.SqlAliasStemHelper; import org.hibernate.sql.ast.spi.SqlAliasStemHelper;
import org.hibernate.sql.ast.tree.from.RootTableGroupProducer; import org.hibernate.sql.ast.tree.from.RootTableGroupProducer;
import org.hibernate.sql.ast.tree.from.TableGroup; import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.tuple.InMemoryGenerator;
import org.hibernate.tuple.entity.EntityMetamodel; import org.hibernate.tuple.entity.EntityMetamodel;
import org.hibernate.type.BasicType; import org.hibernate.type.BasicType;
import org.hibernate.type.Type; import org.hibernate.type.Type;
@ -451,9 +452,16 @@ public interface EntityPersister
* Determine which identifier generation strategy is used for this entity. * Determine which identifier generation strategy is used for this entity.
* *
* @return The identifier generation strategy. * @return The identifier generation strategy.
*
* @deprecated use {@link #getGenerator()}
*/ */
@Deprecated
IdentifierGenerator getIdentifierGenerator(); IdentifierGenerator getIdentifierGenerator();
default InMemoryGenerator getGenerator() {
return getIdentifierGenerator();
}
@Override @Override
default AttributeMapping getAttributeMapping(int position) { default AttributeMapping getAttributeMapping(int position) {
return getAttributeMappings().get( position ); return getAttributeMappings().get( position );

View File

@ -112,7 +112,7 @@ public class UnionSubclassEntityPersister extends AbstractEntityPersister {
super( persistentClass, cacheAccessStrategy, naturalIdRegionAccessStrategy, creationContext ); super( persistentClass, cacheAccessStrategy, naturalIdRegionAccessStrategy, creationContext );
if ( getIdentifierGenerator() instanceof IdentityGenerator ) { if ( getGenerator() instanceof IdentityGenerator ) {
throw new MappingException( throw new MappingException(
"Cannot use identity column key generation with <union-subclass> mapping for: " + "Cannot use identity column key generation with <union-subclass> mapping for: " +
getEntityName() getEntityName()

View File

@ -44,7 +44,6 @@ import org.hibernate.graph.RootGraph;
import org.hibernate.graph.spi.AppliedGraph; import org.hibernate.graph.spi.AppliedGraph;
import org.hibernate.graph.spi.RootGraphImplementor; import org.hibernate.graph.spi.RootGraphImplementor;
import org.hibernate.id.BulkInsertionCapableIdentifierGenerator; import org.hibernate.id.BulkInsertionCapableIdentifierGenerator;
import org.hibernate.id.IdentifierGenerator;
import org.hibernate.id.OptimizableGenerator; import org.hibernate.id.OptimizableGenerator;
import org.hibernate.id.enhanced.Optimizer; import org.hibernate.id.enhanced.Optimizer;
import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreLogging;
@ -108,6 +107,7 @@ import org.hibernate.query.sqm.tree.update.SqmAssignment;
import org.hibernate.query.sqm.tree.update.SqmUpdateStatement; import org.hibernate.query.sqm.tree.update.SqmUpdateStatement;
import org.hibernate.sql.results.internal.TupleMetadata; import org.hibernate.sql.results.internal.TupleMetadata;
import org.hibernate.sql.results.spi.ListResultsConsumer; import org.hibernate.sql.results.spi.ListResultsConsumer;
import org.hibernate.tuple.InMemoryGenerator;
import static org.hibernate.jpa.HibernateHints.HINT_CACHEABLE; import static org.hibernate.jpa.HibernateHints.HINT_CACHEABLE;
import static org.hibernate.jpa.HibernateHints.HINT_CACHE_MODE; import static org.hibernate.jpa.HibernateHints.HINT_CACHE_MODE;
@ -838,8 +838,9 @@ public class QuerySqmImpl<R>
boolean useMultiTableInsert = entityDescriptor.isMultiTable(); boolean useMultiTableInsert = entityDescriptor.isMultiTable();
if ( !useMultiTableInsert && !isSimpleValuesInsert( sqmInsert, entityDescriptor ) ) { if ( !useMultiTableInsert && !isSimpleValuesInsert( sqmInsert, entityDescriptor ) ) {
final IdentifierGenerator identifierGenerator = entityDescriptor.getIdentifierGenerator(); final InMemoryGenerator identifierGenerator = entityDescriptor.getGenerator();
if ( identifierGenerator instanceof BulkInsertionCapableIdentifierGenerator && identifierGenerator instanceof OptimizableGenerator ) { if ( identifierGenerator instanceof BulkInsertionCapableIdentifierGenerator
&& identifierGenerator instanceof OptimizableGenerator ) {
final Optimizer optimizer = ( (OptimizableGenerator) identifierGenerator ).getOptimizer(); final Optimizer optimizer = ( (OptimizableGenerator) identifierGenerator ).getOptimizer();
if ( optimizer != null && optimizer.getIncrementSize() > 1 ) { if ( optimizer != null && optimizer.getIncrementSize() > 1 ) {
useMultiTableInsert = !hasIdentifierAssigned( sqmInsert, entityDescriptor ); useMultiTableInsert = !hasIdentifierAssigned( sqmInsert, entityDescriptor );

View File

@ -21,7 +21,6 @@ import org.hibernate.dialect.temptable.TemporaryTable;
import org.hibernate.engine.jdbc.spi.JdbcServices; import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.id.BulkInsertionCapableIdentifierGenerator; import org.hibernate.id.BulkInsertionCapableIdentifierGenerator;
import org.hibernate.id.IdentifierGenerator;
import org.hibernate.id.OptimizableGenerator; import org.hibernate.id.OptimizableGenerator;
import org.hibernate.id.PostInsertIdentifierGenerator; import org.hibernate.id.PostInsertIdentifierGenerator;
import org.hibernate.id.enhanced.Optimizer; import org.hibernate.id.enhanced.Optimizer;
@ -95,6 +94,7 @@ import org.hibernate.sql.results.graph.DomainResult;
import org.hibernate.sql.results.graph.basic.BasicResult; import org.hibernate.sql.results.graph.basic.BasicResult;
import org.hibernate.sql.results.internal.SqlSelectionImpl; import org.hibernate.sql.results.internal.SqlSelectionImpl;
import org.hibernate.sql.results.spi.ListResultsConsumer; import org.hibernate.sql.results.spi.ListResultsConsumer;
import org.hibernate.tuple.InMemoryGenerator;
import org.hibernate.type.spi.TypeConfiguration; import org.hibernate.type.spi.TypeConfiguration;
/** /**
@ -273,7 +273,7 @@ public class CteInsertHandler implements InsertHandler {
rowNumberColumn rowNumberColumn
); );
} }
if ( !assignsId && entityDescriptor.getIdentifierGenerator() instanceof PostInsertIdentifierGenerator ) { if ( !assignsId && entityDescriptor.getGenerator() instanceof PostInsertIdentifierGenerator ) {
querySpec.getSelectClause().addSqlSelection( querySpec.getSelectClause().addSqlSelection(
new SqlSelectionImpl( new SqlSelectionImpl(
1, 1,
@ -337,7 +337,7 @@ public class CteInsertHandler implements InsertHandler {
processingStateStack.push( oldState ); processingStateStack.push( oldState );
sqmConverter.pruneTableGroupJoins(); sqmConverter.pruneTableGroupJoins();
if ( !assignsId && entityDescriptor.getIdentifierGenerator() instanceof PostInsertIdentifierGenerator ) { if ( !assignsId && entityDescriptor.getGenerator() instanceof PostInsertIdentifierGenerator ) {
// Add the row number to the assignments // Add the row number to the assignments
final CteColumn rowNumberColumn = cteTable.getCteColumns() final CteColumn rowNumberColumn = cteTable.getCteColumns()
.get( cteTable.getCteColumns().size() - 1 ); .get( cteTable.getCteColumns().size() - 1 );
@ -389,7 +389,7 @@ public class CteInsertHandler implements InsertHandler {
); );
final CteColumn idColumn = fullEntityCteTable.getCteColumns().get( 0 ); final CteColumn idColumn = fullEntityCteTable.getCteColumns().get( 0 );
final BasicValuedMapping idType = (BasicValuedMapping) idColumn.getJdbcMapping(); final BasicValuedMapping idType = (BasicValuedMapping) idColumn.getJdbcMapping();
final Optimizer optimizer = ( (OptimizableGenerator) entityDescriptor.getIdentifierGenerator() ).getOptimizer(); final Optimizer optimizer = ( (OptimizableGenerator) entityDescriptor.getGenerator() ).getOptimizer();
final BasicValuedMapping integerType = (BasicValuedMapping) rowNumberColumn.getJdbcMapping(); final BasicValuedMapping integerType = (BasicValuedMapping) rowNumberColumn.getJdbcMapping();
final Expression rowNumberMinusOneModuloIncrement = new BinaryArithmeticExpression( final Expression rowNumberMinusOneModuloIncrement = new BinaryArithmeticExpression(
new BinaryArithmeticExpression( new BinaryArithmeticExpression(
@ -428,7 +428,7 @@ public class CteInsertHandler implements InsertHandler {
rowNumberColumnReference rowNumberColumnReference
) )
); );
final String fragment = ( (BulkInsertionCapableIdentifierGenerator) entityDescriptor.getIdentifierGenerator() ) final String fragment = ( (BulkInsertionCapableIdentifierGenerator) entityDescriptor.getGenerator() )
.determineBulkInsertionIdentifierGenerationSelectFragment( .determineBulkInsertionIdentifierGenerationSelectFragment(
sessionFactory.getSqlStringGenerationContext() sessionFactory.getSqlStringGenerationContext()
); );
@ -581,7 +581,7 @@ public class CteInsertHandler implements InsertHandler {
statement.addCteStatement( entityCte ); statement.addCteStatement( entityCte );
} }
} }
else if ( !assignsId && entityDescriptor.getIdentifierGenerator() instanceof PostInsertIdentifierGenerator ) { else if ( !assignsId && entityDescriptor.getGenerator() instanceof PostInsertIdentifierGenerator ) {
final String baseTableName = "base_" + entityCteTable.getTableExpression(); final String baseTableName = "base_" + entityCteTable.getTableExpression();
final CteStatement baseEntityCte = new CteStatement( final CteStatement baseEntityCte = new CteStatement(
entityCteTable.withName( baseTableName ), entityCteTable.withName( baseTableName ),
@ -775,7 +775,7 @@ public class CteInsertHandler implements InsertHandler {
true true
); );
final IdentifierGenerator identifierGenerator = entityDescriptor.getEntityPersister().getIdentifierGenerator(); final InMemoryGenerator identifierGenerator = entityDescriptor.getEntityPersister().getGenerator();
final List<Map.Entry<List<CteColumn>, Assignment>> tableAssignments = assignmentsByTable.get( rootTableReference ); final List<Map.Entry<List<CteColumn>, Assignment>> tableAssignments = assignmentsByTable.get( rootTableReference );
if ( ( tableAssignments == null || tableAssignments.isEmpty() ) && !( identifierGenerator instanceof PostInsertIdentifierGenerator ) ) { if ( ( tableAssignments == null || tableAssignments.isEmpty() ) && !( identifierGenerator instanceof PostInsertIdentifierGenerator ) ) {
throw new IllegalStateException( "There must be at least a single root table assignment" ); throw new IllegalStateException( "There must be at least a single root table assignment" );

View File

@ -23,7 +23,6 @@ import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.id.BulkInsertionCapableIdentifierGenerator; import org.hibernate.id.BulkInsertionCapableIdentifierGenerator;
import org.hibernate.id.IdentifierGenerator;
import org.hibernate.id.OptimizableGenerator; import org.hibernate.id.OptimizableGenerator;
import org.hibernate.id.PostInsertIdentifierGenerator; import org.hibernate.id.PostInsertIdentifierGenerator;
import org.hibernate.id.PostInsertIdentityPersister; import org.hibernate.id.PostInsertIdentityPersister;
@ -74,6 +73,7 @@ import org.hibernate.sql.exec.spi.JdbcParameterBindings;
import org.hibernate.sql.results.graph.basic.BasicFetch; import org.hibernate.sql.results.graph.basic.BasicFetch;
import org.hibernate.sql.results.internal.SqlSelectionImpl; import org.hibernate.sql.results.internal.SqlSelectionImpl;
import org.hibernate.sql.results.spi.ListResultsConsumer; import org.hibernate.sql.results.spi.ListResultsConsumer;
import org.hibernate.tuple.InMemoryGenerator;
import org.hibernate.type.descriptor.ValueBinder; import org.hibernate.type.descriptor.ValueBinder;
/** /**
@ -301,7 +301,7 @@ public class InsertExecutionDelegate implements TableBasedInsertHandler.Executio
true true
); );
final IdentifierGenerator identifierGenerator = entityDescriptor.getEntityPersister().getIdentifierGenerator(); final InMemoryGenerator identifierGenerator = entityDescriptor.getEntityPersister().getGenerator();
final List<Assignment> assignments = assignmentsByTable.get( updatingTableReference ); final List<Assignment> assignments = assignmentsByTable.get( updatingTableReference );
if ( ( assignments == null || assignments.isEmpty() ) if ( ( assignments == null || assignments.isEmpty() )
&& !( identifierGenerator instanceof PostInsertIdentifierGenerator ) && !( identifierGenerator instanceof PostInsertIdentifierGenerator )
@ -507,10 +507,7 @@ public class InsertExecutionDelegate implements TableBasedInsertHandler.Executio
rootIdentity, rootIdentity,
new JdbcParameterBindingImpl( new JdbcParameterBindingImpl(
identifierMapping.getJdbcMapping(), identifierMapping.getJdbcMapping(),
identifierGenerator.generate( identifierGenerator.generate( executionContext.getSession(), null, null )
executionContext.getSession(),
null
)
) )
); );
jdbcServices.getJdbcMutationExecutor().execute( jdbcServices.getJdbcMutationExecutor().execute(
@ -654,7 +651,7 @@ public class InsertExecutionDelegate implements TableBasedInsertHandler.Executio
} }
} }
private boolean needsIdentifierGeneration(IdentifierGenerator identifierGenerator) { private boolean needsIdentifierGeneration(InMemoryGenerator identifierGenerator) {
if ( !( identifierGenerator instanceof OptimizableGenerator ) ) { if ( !( identifierGenerator instanceof OptimizableGenerator ) ) {
return false; return false;
} }
@ -721,7 +718,7 @@ public class InsertExecutionDelegate implements TableBasedInsertHandler.Executio
} }
final String targetKeyColumnName = keyColumns[0]; final String targetKeyColumnName = keyColumns[0];
final AbstractEntityPersister entityPersister = (AbstractEntityPersister) entityDescriptor.getEntityPersister(); final AbstractEntityPersister entityPersister = (AbstractEntityPersister) entityDescriptor.getEntityPersister();
final IdentifierGenerator identifierGenerator = entityPersister.getIdentifierGenerator(); final InMemoryGenerator identifierGenerator = entityPersister.getGenerator();
final boolean needsKeyInsert; final boolean needsKeyInsert;
if ( identifierGenerator instanceof PostInsertIdentifierGenerator ) { if ( identifierGenerator instanceof PostInsertIdentifierGenerator ) {
needsKeyInsert = true; needsKeyInsert = true;

View File

@ -20,7 +20,6 @@ import org.hibernate.dialect.temptable.TemporaryTableColumn;
import org.hibernate.dialect.temptable.TemporaryTableSessionUidColumn; import org.hibernate.dialect.temptable.TemporaryTableSessionUidColumn;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.id.IdentifierGenerator;
import org.hibernate.id.OptimizableGenerator; import org.hibernate.id.OptimizableGenerator;
import org.hibernate.id.enhanced.Optimizer; import org.hibernate.id.enhanced.Optimizer;
import org.hibernate.internal.util.collections.CollectionHelper; import org.hibernate.internal.util.collections.CollectionHelper;
@ -53,6 +52,7 @@ import org.hibernate.sql.ast.tree.update.Assignment;
import org.hibernate.sql.exec.internal.JdbcParameterImpl; import org.hibernate.sql.exec.internal.JdbcParameterImpl;
import org.hibernate.sql.exec.spi.ExecutionContext; import org.hibernate.sql.exec.spi.ExecutionContext;
import org.hibernate.sql.results.internal.SqlSelectionImpl; import org.hibernate.sql.results.internal.SqlSelectionImpl;
import org.hibernate.tuple.InMemoryGenerator;
import org.hibernate.type.BasicType; import org.hibernate.type.BasicType;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
@ -201,8 +201,8 @@ public class TableBasedInsertHandler implements InsertHandler {
new Assignment( columnReference, columnReference ) new Assignment( columnReference, columnReference )
); );
} }
else if ( entityDescriptor.getIdentifierGenerator() instanceof OptimizableGenerator ) { else if ( entityDescriptor.getGenerator() instanceof OptimizableGenerator ) {
final Optimizer optimizer = ( (OptimizableGenerator) entityDescriptor.getIdentifierGenerator() ).getOptimizer(); final Optimizer optimizer = ( (OptimizableGenerator) entityDescriptor.getGenerator() ).getOptimizer();
if ( optimizer != null && optimizer.getIncrementSize() > 1 ) { if ( optimizer != null && optimizer.getIncrementSize() > 1 ) {
if ( !sessionFactory.getJdbcServices().getDialect().supportsWindowFunctions() ) { if ( !sessionFactory.getJdbcServices().getDialect().supportsWindowFunctions() ) {
return; return;
@ -254,7 +254,7 @@ public class TableBasedInsertHandler implements InsertHandler {
} }
else { else {
// Add the row number column if there is one // Add the row number column if there is one
final IdentifierGenerator generator = entityDescriptor.getIdentifierGenerator(); final InMemoryGenerator generator = entityDescriptor.getGenerator();
final BasicType<?> rowNumberType; final BasicType<?> rowNumberType;
if ( generator instanceof OptimizableGenerator ) { if ( generator instanceof OptimizableGenerator ) {
final Optimizer optimizer = ( (OptimizableGenerator) generator ).getOptimizer(); final Optimizer optimizer = ( (OptimizableGenerator) generator ).getOptimizer();

View File

@ -44,7 +44,6 @@ import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.graph.spi.AppliedGraph; import org.hibernate.graph.spi.AppliedGraph;
import org.hibernate.id.BulkInsertionCapableIdentifierGenerator; import org.hibernate.id.BulkInsertionCapableIdentifierGenerator;
import org.hibernate.id.CompositeNestedGeneratedValueGenerator; import org.hibernate.id.CompositeNestedGeneratedValueGenerator;
import org.hibernate.id.IdentifierGenerator;
import org.hibernate.id.OptimizableGenerator; import org.hibernate.id.OptimizableGenerator;
import org.hibernate.id.PostInsertIdentifierGenerator; import org.hibernate.id.PostInsertIdentifierGenerator;
import org.hibernate.id.enhanced.Optimizer; import org.hibernate.id.enhanced.Optimizer;
@ -384,6 +383,7 @@ import org.hibernate.sql.results.graph.FetchableContainer;
import org.hibernate.sql.results.graph.instantiation.internal.DynamicInstantiation; import org.hibernate.sql.results.graph.instantiation.internal.DynamicInstantiation;
import org.hibernate.sql.results.internal.SqlSelectionImpl; import org.hibernate.sql.results.internal.SqlSelectionImpl;
import org.hibernate.sql.results.internal.StandardEntityGraphTraversalStateImpl; import org.hibernate.sql.results.internal.StandardEntityGraphTraversalStateImpl;
import org.hibernate.tuple.InMemoryGenerator;
import org.hibernate.type.BasicType; import org.hibernate.type.BasicType;
import org.hibernate.type.CustomType; import org.hibernate.type.CustomType;
import org.hibernate.type.EnumType; import org.hibernate.type.EnumType;
@ -1225,18 +1225,13 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
EntityPersister entityDescriptor, TableGroup rootTableGroup) { EntityPersister entityDescriptor, TableGroup rootTableGroup) {
final List<SqmPath<?>> targetPaths = sqmStatement.getInsertionTargetPaths(); final List<SqmPath<?>> targetPaths = sqmStatement.getInsertionTargetPaths();
final EntityDiscriminatorMapping discriminatorMapping = entityDescriptor.getDiscriminatorMapping(); final EntityDiscriminatorMapping discriminatorMapping = entityDescriptor.getDiscriminatorMapping();
IdentifierGenerator identifierGenerator = entityDescriptor.getIdentifierGenerator();
Expression versionExpression = null; Expression versionExpression = null;
Expression discriminatorExpression = null; Expression discriminatorExpression = null;
BasicEntityIdentifierMapping identifierMapping = null; BasicEntityIdentifierMapping identifierMapping = null;
// We use the id property name to null the identifier generator variable if the target paths contain the id // We use the id property name to null the identifier generator variable if the target paths contain the id
final String identifierPropertyName; final String identifierPropertyName;
if ( identifierGenerator != null ) { InMemoryGenerator identifierGenerator = entityDescriptor.getGenerator();
identifierPropertyName = entityDescriptor.getIdentifierPropertyName(); identifierPropertyName = identifierGenerator != null ? entityDescriptor.getIdentifierPropertyName() : null;
}
else {
identifierPropertyName = null;
}
final String versionAttributeName; final String versionAttributeName;
boolean needsVersionInsert; boolean needsVersionInsert;
if ( entityDescriptor.isVersioned() ) { if ( entityDescriptor.isVersioned() ) {
@ -1351,7 +1346,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
public static class AdditionalInsertValues { public static class AdditionalInsertValues {
private final Expression versionExpression; private final Expression versionExpression;
private final Expression discriminatorExpression; private final Expression discriminatorExpression;
private final IdentifierGenerator identifierGenerator; private final InMemoryGenerator identifierGenerator;
private final BasicEntityIdentifierMapping identifierMapping; private final BasicEntityIdentifierMapping identifierMapping;
private Expression identifierGeneratorParameter; private Expression identifierGeneratorParameter;
private SqlSelection versionSelection; private SqlSelection versionSelection;
@ -1361,7 +1356,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
public AdditionalInsertValues( public AdditionalInsertValues(
Expression versionExpression, Expression versionExpression,
Expression discriminatorExpression, Expression discriminatorExpression,
IdentifierGenerator identifierGenerator, InMemoryGenerator identifierGenerator,
BasicEntityIdentifierMapping identifierMapping) { BasicEntityIdentifierMapping identifierMapping) {
this.versionExpression = versionExpression; this.versionExpression = versionExpression;
this.discriminatorExpression = discriminatorExpression; this.discriminatorExpression = discriminatorExpression;
@ -1453,9 +1448,9 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
private static class IdGeneratorParameter extends AbstractJdbcParameter { private static class IdGeneratorParameter extends AbstractJdbcParameter {
private final IdentifierGenerator generator; private final InMemoryGenerator generator;
public IdGeneratorParameter(BasicEntityIdentifierMapping identifierMapping, IdentifierGenerator generator) { public IdGeneratorParameter(BasicEntityIdentifierMapping identifierMapping, InMemoryGenerator generator) {
super( identifierMapping.getJdbcMapping() ); super( identifierMapping.getJdbcMapping() );
this.generator = generator; this.generator = generator;
} }
@ -1468,7 +1463,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
ExecutionContext executionContext) throws SQLException { ExecutionContext executionContext) throws SQLException {
getJdbcMapping().getJdbcValueBinder().bind( getJdbcMapping().getJdbcValueBinder().bind(
statement, statement,
generator.generate( executionContext.getSession(), null ), generator.generate( executionContext.getSession(), null, null ),
startPosition, startPosition,
executionContext.getSession() executionContext.getSession()
); );

View File

@ -11,18 +11,22 @@ import java.lang.reflect.Member;
/** /**
* A {@link Generator} based on a custom Java generator annotation type. * A {@link Generator} which receives parameters from a custom
* Every instance must implement either {@link InMemoryGenerator} or * {@linkplain org.hibernate.annotations.ValueGenerationType generator annotation} or
* {@link InDatabaseGenerator}. Implementing this interface is just a * {@linkplain org.hibernate.annotations.IdGeneratorType id generator annotation}.
* slightly more typesafe alternative to providing a constructor with * <p>
* the same signature as the method * Implementing this interface is the same as providing a constructor with the same
* {@link #initialize(Annotation, Member, GeneratorCreationContext)}. * signature as the {@link #initialize} method. But implementing this interface is
* slightly more typesafe.
* <p>
* Every instance of this class must implement either {@link InMemoryGenerator} or
* {@link InDatabaseGenerator}.
* *
* @param <A> The generator annotation type supported by an implementation * @param <A> The generator annotation type supported by an implementation
* *
* @see org.hibernate.annotations.ValueGenerationType * @see org.hibernate.annotations.ValueGenerationType
* @see org.hibernate.annotations.IdGeneratorType
* *
* @author Gunnar Morling
* @author Gavin King * @author Gavin King
* *
* @since 6.2 * @since 6.2
@ -31,8 +35,9 @@ public interface AnnotationBasedGenerator<A extends Annotation> extends Generato
/** /**
* Initializes this generation strategy for the given annotation instance. * Initializes this generation strategy for the given annotation instance.
* *
* @param annotation an instance of the strategy's annotation type. Typically, implementations will retrieve the * @param annotation an instance of the strategy's annotation type. Typically,
* annotation's attribute values and store them in fields. * implementations will retrieve the annotation's attribute
* values and store them in fields.
* @param member the Java member annotated with the generator annotation. * @param member the Java member annotated with the generator annotation.
* @param context a {@link GeneratorCreationContext} * @param context a {@link GeneratorCreationContext}
* @throws org.hibernate.HibernateException in case an error occurred during initialization, e.g. if * @throws org.hibernate.HibernateException in case an error occurred during initialization, e.g. if

View File

@ -15,23 +15,29 @@ import java.lang.reflect.Method;
/** /**
* A {@link ValueGeneration} based on a custom Java generator annotation type. * An implementation of {@link ValueGeneration} which receives parameters from a custom
* {@linkplain org.hibernate.annotations.ValueGenerationType generator annotation}.
* <p>
* This is an older API that predates {@link Generator} and {@link AnnotationBasedGenerator}.
* It's often cleaner to implement {@code AnnotationBasedGenerator} directly.
* *
* @param <A> The generator annotation type supported by an implementation * @param <A> The generator annotation type supported by an implementation
* *
* @see org.hibernate.annotations.ValueGenerationType * @see org.hibernate.annotations.ValueGenerationType
* *
* @author Gunnar Morling * @author Gunnar Morling
*
* @see ValueGeneration
*/ */
public interface AnnotationValueGeneration<A extends Annotation> public interface AnnotationValueGeneration<A extends Annotation>
extends ValueGeneration, AnnotationBasedGenerator<A> { extends ValueGeneration, AnnotationBasedGenerator<A> {
/** /**
* Initializes this generation strategy for the given annotation instance. * Initializes this generation strategy for the given annotation instance.
* *
* @param annotation an instance of the strategy's annotation type. Typically, implementations will retrieve the * @param annotation an instance of the strategy's annotation type. Typically,
* annotation's attribute values and store them in fields. * implementations will retrieve the annotation's attribute
* @param propertyType the type of the property annotated with the generator annotation. Implementations may use * values and store them in fields.
* the type to determine the right {@link ValueGenerator} to be applied. * @param propertyType the type of the property annotated with the generator annotation.
* @throws org.hibernate.HibernateException in case an error occurred during initialization, e.g. if * @throws org.hibernate.HibernateException in case an error occurred during initialization, e.g. if
* an implementation can't create a value for the given property type. * an implementation can't create a value for the given property type.
*/ */

View File

@ -6,15 +6,18 @@
*/ */
package org.hibernate.tuple; package org.hibernate.tuple;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import java.io.Serializable; import java.io.Serializable;
/** /**
* Describes the generation of values of a certain field or property of an entity. A generated * Describes the generation of values of a certain field or property of an entity. A generated
* value might be generated in Java, or by the database. Every instance must implement either * value might be generated in Java, or by the database. Every instance must implement either
* {@link InMemoryGenerator} or {@link InDatabaseGenerator} * {@link InMemoryGenerator} or {@link InDatabaseGenerator} depending on whether values are
* depending on whether values are generated in Java code, or by the database. * generated in Java code, or by the database.
* <ul> * <ul>
* <li>Java value generation is the responsibility of an associated {@link ValueGenerator}. * <li>Value generation via arbitrary code written in Java is the responsibility of the method
* {@link InMemoryGenerator#generate(SharedSessionContractImplementor, Object, Object)}.
* 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
* or property value. * or property value.
* <li>A value generated by the database might be generated implicitly, by a trigger, or using * <li>A value generated by the database might be generated implicitly, by a trigger, or using
@ -23,11 +26,21 @@ import java.io.Serializable;
* statement. In this case, the generated value is retrieved from the database using a SQL * statement. In this case, the generated value is retrieved from the database using a SQL
* {@code select}. * {@code select}.
* </ul> * </ul>
* If an implementation of {@code ValueGenerationStrategy} may be associated with an entity * A generator may receive parameters from {@linkplain org.hibernate.annotations.ValueGenerationType
* via a {@linkplain org.hibernate.annotations.ValueGenerationType custom annotation}, it * an annotation}. The generator may either:
* should implement {@link AnnotationBasedGenerator}. * <ul>
* <li>implement {@link AnnotationBasedGenerator}, and receive the annotation as an argument to
* {@link AnnotationBasedGenerator#initialize},
* <li>declare a constructor with the same signature as {@link AnnotationBasedGenerator#initialize},
* <li>declare a constructor which accepts just the annotation instance, or
* <li>declare a only default constructor, in which case it will not receive parameters.
* </ul>
* On the other hand, there is some special machinery for configuring the much older interface
* {@link org.hibernate.id.IdentifierGenerator}. But this machinery is only available for
* identifier generation.
* *
* @see org.hibernate.annotations.ValueGenerationType * @see org.hibernate.annotations.ValueGenerationType
* @see org.hibernate.annotations.IdGeneratorType
* @see org.hibernate.annotations.Generated * @see org.hibernate.annotations.Generated
* @see org.hibernate.annotations.GeneratorType * @see org.hibernate.annotations.GeneratorType
* *

View File

@ -16,8 +16,11 @@ public interface IdentifierAttribute extends Attribute {
boolean isEmbedded(); boolean isEmbedded();
@Deprecated
IdentifierGenerator getIdentifierGenerator(); IdentifierGenerator getIdentifierGenerator();
InMemoryGenerator getGenerator();
boolean isIdentifierAssignedByInsert(); boolean isIdentifierAssignedByInsert();
boolean hasIdentifierMapper(); boolean hasIdentifierMapper();

View File

@ -20,7 +20,7 @@ public class IdentifierProperty extends AbstractAttribute implements IdentifierA
private final boolean virtual; private final boolean virtual;
private final boolean embedded; private final boolean embedded;
private final IdentifierGenerator identifierGenerator; private final InMemoryGenerator identifierGenerator;
private final boolean identifierAssignedByInsert; private final boolean identifierAssignedByInsert;
private final boolean hasIdentifierMapper; private final boolean hasIdentifierMapper;
@ -38,7 +38,7 @@ public class IdentifierProperty extends AbstractAttribute implements IdentifierA
String name, String name,
Type type, Type type,
boolean embedded, boolean embedded,
IdentifierGenerator identifierGenerator) { InMemoryGenerator identifierGenerator) {
super( name, type ); super( name, type );
this.virtual = false; this.virtual = false;
this.embedded = embedded; this.embedded = embedded;
@ -59,7 +59,7 @@ public class IdentifierProperty extends AbstractAttribute implements IdentifierA
Type type, Type type,
boolean embedded, boolean embedded,
boolean hasIdentifierMapper, boolean hasIdentifierMapper,
IdentifierGenerator identifierGenerator) { InMemoryGenerator identifierGenerator) {
super( null, type ); super( null, type );
this.virtual = true; this.virtual = true;
this.embedded = embedded; this.embedded = embedded;
@ -80,6 +80,11 @@ public class IdentifierProperty extends AbstractAttribute implements IdentifierA
@Override @Override
public IdentifierGenerator getIdentifierGenerator() { public IdentifierGenerator getIdentifierGenerator() {
return (IdentifierGenerator) identifierGenerator;
}
@Override
public InMemoryGenerator getGenerator() {
return identifierGenerator; return identifierGenerator;
} }

View File

@ -14,6 +14,10 @@ import org.hibernate.dialect.Dialect;
* by a SQL expression occurring explicitly in the SQL {@code insert} or {@code update} * by a SQL expression occurring explicitly in the SQL {@code insert} or {@code update}
* statement. In this case, the generated value is retrieved from the database using a SQL * statement. In this case, the generated value is retrieved from the database using a SQL
* {@code select}. * {@code select}.
* <p>
* Implementations should override {@link #referenceColumnsInSql()},
* {@link #writePropertyValue()}, and {@link #getReferencedColumnValues(Dialect)} as needed
* in order to achieve the desired behavior.
* *
* @author Steve Ebersole * @author Steve Ebersole
* *
@ -22,9 +26,9 @@ import org.hibernate.dialect.Dialect;
public interface InDatabaseGenerator extends Generator { public interface InDatabaseGenerator extends Generator {
/** /**
* Determines if the columns whose values are generated are included in the column list of * Determines if the columns whose values are generated are included in the column list
* the SQL {@code insert} or {@code update} statement, in the case where the value is * of the SQL {@code insert} or {@code update} statement. For example, this method should
* generated by the database. For example, this method should return: * return:
* <ul> * <ul>
* <li>{@code true} if the value is generated by calling a SQL function like * <li>{@code true} if the value is generated by calling a SQL function like
* {@code current_timestamp}, or * {@code current_timestamp}, or
@ -32,10 +36,6 @@ public interface InDatabaseGenerator extends Generator {
* by {@link org.hibernate.annotations.GeneratedColumn generated always as}, or * by {@link org.hibernate.annotations.GeneratedColumn generated always as}, or
* using a {@linkplain org.hibernate.annotations.ColumnDefault column default value}. * using a {@linkplain org.hibernate.annotations.ColumnDefault column default value}.
* </ul> * </ul>
* If the value is generated in Java, this method is not called, and so for backward
* compatibility with Hibernate 5 it is permitted to return any value. On the other hand,
* when a property value is generated in Java, the column certainly must be included in
* the column list, and so it's most correct for this method to return {@code true}!
* *
* @return {@code true} if the column is included in the column list of the SQL statement. * @return {@code true} if the column is included in the column list of the SQL statement.
*/ */
@ -48,18 +48,16 @@ public interface InDatabaseGenerator extends Generator {
boolean writePropertyValue(); boolean writePropertyValue();
/** /**
* A SQL expression indicating how to calculate the generated values when the property values * A SQL expression indicating how to calculate the generated values when the mapped columns
* are {@linkplain #generatedByDatabase() generated in the database} and the mapped columns
* are {@linkplain #referenceColumnsInSql() included in the SQL statement}. The SQL expressions * are {@linkplain #referenceColumnsInSql() included in the SQL statement}. The SQL expressions
* might be: * might be:
* <ul> * <ul>
* <li>function calls like {@code current_timestamp} or {@code nextval('mysequence')}, or * <li>function calls like {@code current_timestamp} or {@code nextval('mysequence')}, or
* <li>syntactic markers like {@code default}. * <li>syntactic markers like {@code default}.
* </ul> * </ul>
* When the property values are generated in Java, this method is not called.
* *
* @param dialect The {@linkplain Dialect SQL dialect}, allowing generation of an expression * @param dialect The {@linkplain Dialect SQL dialect}, allowing generation of an expression
* in dialect-specific SQL. * in dialect-specific SQL.
* @return The column value to be used in the generated SQL statement. * @return The column value to be used in the generated SQL statement.
*/ */
String[] getReferencedColumnValues(Dialect dialect); String[] getReferencedColumnValues(Dialect dialect);

View File

@ -9,9 +9,16 @@ package org.hibernate.tuple;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
/** /**
* Java value generation is the responsibility of an associated {@link ValueGenerator}. * A generator that is called to produce a value just before a row is written to the database.
* In this case, the generated value is written to the database just like any other field * The {@link #generate} method may execute arbitrary Java code, it may even, in principle,
* or property value. * access the database via JDBC. But however it is produced, the generated value is sent to the
* database via a parameter of a JDBC prepared statement, just like any other field or property
* value.
* <p>
* Any {@link InMemoryGenerator} may be used to produce {@linkplain jakarta.persistence.Id
* identifiers}. The built-in identifier generators all implement the older extension point
* {@link org.hibernate.id.IdentifierGenerator}, which is a subtype of this interface, but that
* is no longer a requirement for custom id generators.
* *
* @author Steve Ebersole * @author Steve Ebersole
* *

View File

@ -11,7 +11,6 @@ import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.boot.spi.SessionFactoryOptions; import org.hibernate.boot.spi.SessionFactoryOptions;
import org.hibernate.bytecode.enhance.spi.interceptor.EnhancementHelper; import org.hibernate.bytecode.enhance.spi.interceptor.EnhancementHelper;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.id.IdentifierGenerator;
import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property; import org.hibernate.mapping.Property;
import org.hibernate.metamodel.spi.RuntimeModelCreationContext; import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
@ -44,7 +43,7 @@ public final class PropertyFactory {
*/ */
public static IdentifierProperty buildIdentifierAttribute( public static IdentifierProperty buildIdentifierAttribute(
PersistentClass mappedEntity, PersistentClass mappedEntity,
IdentifierGenerator generator) { InMemoryGenerator generator) {
Type type = mappedEntity.getIdentifier().getType(); Type type = mappedEntity.getIdentifier().getType();
Property property = mappedEntity.getIdentifierProperty(); Property property = mappedEntity.getIdentifierProperty();

View File

@ -11,11 +11,15 @@ import org.hibernate.dialect.Dialect;
import org.hibernate.engine.spi.SharedSessionContractImplementor; 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 generation.
* generation. * <p>
* This is an older API that predates {@link Generator}. It's often cleaner to implement either
* {@link InMemoryGenerator} or {@link InDatabaseGenerator} directly.
* *
* @author Steve Ebersole * @author Steve Ebersole
* @author Gavin King * @author Gavin King
*
* @see AnnotationValueGeneration
*/ */
public interface ValueGeneration extends InMemoryGenerator, InDatabaseGenerator { public interface ValueGeneration extends InMemoryGenerator, InDatabaseGenerator {
/** /**

View File

@ -158,7 +158,7 @@ public class EntityMetamodel implements Serializable {
identifierAttribute = PropertyFactory.buildIdentifierAttribute( identifierAttribute = PropertyFactory.buildIdentifierAttribute(
persistentClass, persistentClass,
sessionFactory.getIdentifierGenerator( rootName ) sessionFactory.getGenerator( rootName )
); );
versioned = persistentClass.isVersioned(); versioned = persistentClass.isVersioned();

View File

@ -37,10 +37,8 @@ import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.testing.TestForIssue; import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.orm.junit.DomainModel; import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.SessionFactory; import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope; import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.hibernate.testing.orm.junit.Setting;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;

View File

@ -36,9 +36,9 @@ public class BasicForcedTableSequenceTest {
final EntityPersister persister = scope.getSessionFactory() final EntityPersister persister = scope.getSessionFactory()
.getMappingMetamodel() .getMappingMetamodel()
.getEntityDescriptor(Entity.class.getName()); .getEntityDescriptor(Entity.class.getName());
assertThat( persister.getIdentifierGenerator(), instanceOf( SequenceStyleGenerator.class ) ); assertThat( persister.getGenerator(), instanceOf( SequenceStyleGenerator.class ) );
final SequenceStyleGenerator generator = ( SequenceStyleGenerator ) persister.getIdentifierGenerator(); final SequenceStyleGenerator generator = (SequenceStyleGenerator) persister.getGenerator();
assertThat( generator.getDatabaseStructure(), instanceOf( TableStructure.class ) ); assertThat( generator.getDatabaseStructure(), instanceOf( TableStructure.class ) );
assertThat( generator.getOptimizer(), instanceOf( NoopOptimizer.class ) ); assertThat( generator.getOptimizer(), instanceOf( NoopOptimizer.class ) );

View File

@ -40,9 +40,9 @@ public class BasicSequenceTest {
final EntityPersister persister = scope.getSessionFactory() final EntityPersister persister = scope.getSessionFactory()
.getMappingMetamodel() .getMappingMetamodel()
.getEntityDescriptor(Entity.class.getName()); .getEntityDescriptor(Entity.class.getName());
assertThat( persister.getIdentifierGenerator(), instanceOf( SequenceStyleGenerator.class ) ); assertThat( persister.getGenerator(), instanceOf( SequenceStyleGenerator.class ) );
final SequenceStyleGenerator generator = (SequenceStyleGenerator) persister.getIdentifierGenerator(); final SequenceStyleGenerator generator = (SequenceStyleGenerator) persister.getGenerator();
final int count = 5; final int count = 5;
@ -71,9 +71,9 @@ public class BasicSequenceTest {
final EntityPersister persister = scope.getSessionFactory() final EntityPersister persister = scope.getSessionFactory()
.getMappingMetamodel() .getMappingMetamodel()
.getEntityDescriptor(overriddenEntityName); .getEntityDescriptor(overriddenEntityName);
assertThat( persister.getIdentifierGenerator(), instanceOf( SequenceStyleGenerator.class ) ); assertThat( persister.getGenerator(), instanceOf( SequenceStyleGenerator.class ) );
final SequenceStyleGenerator generator = (SequenceStyleGenerator) persister.getIdentifierGenerator(); final SequenceStyleGenerator generator = (SequenceStyleGenerator) persister.getGenerator();
assertEquals( "ID_SEQ_BSC_ENTITY" + SequenceStyleGenerator.DEF_SEQUENCE_SUFFIX, assertEquals( "ID_SEQ_BSC_ENTITY" + SequenceStyleGenerator.DEF_SEQUENCE_SUFFIX,
generator.getDatabaseStructure().getPhysicalName().render() ); generator.getDatabaseStructure().getPhysicalName().render() );

View File

@ -29,9 +29,9 @@ public class BasicTableTest {
final EntityPersister persister = scope.getSessionFactory() final EntityPersister persister = scope.getSessionFactory()
.getMappingMetamodel() .getMappingMetamodel()
.getEntityDescriptor(Entity.class.getName()); .getEntityDescriptor(Entity.class.getName());
assertThat( persister.getIdentifierGenerator(), instanceOf( TableGenerator.class ) ); assertThat( persister.getGenerator(), instanceOf( TableGenerator.class ) );
final TableGenerator generator = ( TableGenerator ) persister.getIdentifierGenerator(); final TableGenerator generator = ( TableGenerator ) persister.getGenerator();
scope.inTransaction( scope.inTransaction(
(s) -> { (s) -> {

View File

@ -39,7 +39,6 @@ import org.hibernate.resource.beans.container.spi.BeanContainer;
import org.hibernate.resource.beans.container.spi.BeanContainer.LifecycleOptions; import org.hibernate.resource.beans.container.spi.BeanContainer.LifecycleOptions;
import org.hibernate.resource.beans.container.spi.ContainedBean; import org.hibernate.resource.beans.container.spi.ContainedBean;
import org.hibernate.resource.beans.internal.FallbackBeanInstanceProducer; import org.hibernate.resource.beans.internal.FallbackBeanInstanceProducer;
import org.hibernate.service.spi.ServiceRegistryImplementor;
import org.hibernate.testing.TestForIssue; import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.orm.junit.BaseUnitTest; import org.hibernate.testing.orm.junit.BaseUnitTest;