HHH-18498 - Support for unnamed generators
HHH-18593 - Enforce GeneratedValue GenerationType HHH-18609 - Use UuidGenerator for GenerationType.UUID
This commit is contained in:
parent
76df41f9be
commit
4b6822a8bc
|
@ -46,7 +46,8 @@ import org.hibernate.boot.model.internal.AggregateComponentSecondPass;
|
||||||
import org.hibernate.boot.model.internal.AnnotatedClassType;
|
import org.hibernate.boot.model.internal.AnnotatedClassType;
|
||||||
import org.hibernate.boot.model.internal.CreateKeySecondPass;
|
import org.hibernate.boot.model.internal.CreateKeySecondPass;
|
||||||
import org.hibernate.boot.model.internal.FkSecondPass;
|
import org.hibernate.boot.model.internal.FkSecondPass;
|
||||||
import org.hibernate.boot.model.internal.IdGeneratorResolverSecondPass;
|
import org.hibernate.boot.model.internal.IdBagIdGeneratorResolverSecondPass;
|
||||||
|
import org.hibernate.boot.model.internal.IdGeneratorResolver;
|
||||||
import org.hibernate.boot.model.internal.ImplicitToOneJoinTableSecondPass;
|
import org.hibernate.boot.model.internal.ImplicitToOneJoinTableSecondPass;
|
||||||
import org.hibernate.boot.model.internal.OptionalDeterminationSecondPass;
|
import org.hibernate.boot.model.internal.OptionalDeterminationSecondPass;
|
||||||
import org.hibernate.boot.model.internal.QuerySecondPass;
|
import org.hibernate.boot.model.internal.QuerySecondPass;
|
||||||
|
@ -714,9 +715,14 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector,
|
||||||
throw new IllegalArgumentException( "ID generator object or name is null." );
|
throw new IllegalArgumentException( "ID generator object or name is null." );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( generator.getName().isEmpty() ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if ( defaultIdentifierGeneratorNames.contains( generator.getName() ) ) {
|
if ( defaultIdentifierGeneratorNames.contains( generator.getName() ) ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final IdentifierGeneratorDefinition old = idGeneratorDefinitionMap.put( generator.getName(), generator );
|
final IdentifierGeneratorDefinition old = idGeneratorDefinitionMap.put( generator.getName(), generator );
|
||||||
if ( old != null && !old.equals( generator ) ) {
|
if ( old != null && !old.equals( generator ) ) {
|
||||||
if ( bootstrapContext.getJpaCompliance().isGlobalGeneratorScopeEnabled() ) {
|
if ( bootstrapContext.getJpaCompliance().isGlobalGeneratorScopeEnabled() ) {
|
||||||
|
@ -1675,7 +1681,7 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ArrayList<IdGeneratorResolverSecondPass> idGeneratorResolverSecondPassList;
|
private ArrayList<IdGeneratorResolver> idGeneratorResolverSecondPassList;
|
||||||
private ArrayList<SetBasicValueTypeSecondPass> setBasicValueTypeSecondPassList;
|
private ArrayList<SetBasicValueTypeSecondPass> setBasicValueTypeSecondPassList;
|
||||||
private ArrayList<AggregateComponentSecondPass> aggregateComponentSecondPassList;
|
private ArrayList<AggregateComponentSecondPass> aggregateComponentSecondPassList;
|
||||||
private ArrayList<FkSecondPass> fkSecondPassList;
|
private ArrayList<FkSecondPass> fkSecondPassList;
|
||||||
|
@ -1696,8 +1702,8 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector,
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addSecondPass(SecondPass secondPass, boolean onTopOfTheQueue) {
|
public void addSecondPass(SecondPass secondPass, boolean onTopOfTheQueue) {
|
||||||
if ( secondPass instanceof IdGeneratorResolverSecondPass ) {
|
if ( secondPass instanceof IdGeneratorResolver ) {
|
||||||
addIdGeneratorResolverSecondPass( (IdGeneratorResolverSecondPass) secondPass, onTopOfTheQueue );
|
addIdGeneratorResolverSecondPass( (IdGeneratorResolver) secondPass, onTopOfTheQueue );
|
||||||
}
|
}
|
||||||
else if ( secondPass instanceof SetBasicValueTypeSecondPass ) {
|
else if ( secondPass instanceof SetBasicValueTypeSecondPass ) {
|
||||||
addSetBasicValueTypeSecondPass( (SetBasicValueTypeSecondPass) secondPass, onTopOfTheQueue );
|
addSetBasicValueTypeSecondPass( (SetBasicValueTypeSecondPass) secondPass, onTopOfTheQueue );
|
||||||
|
@ -1764,7 +1770,7 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector,
|
||||||
addSecondPass( secondPass, aggregateComponentSecondPassList, onTopOfTheQueue );
|
addSecondPass( secondPass, aggregateComponentSecondPassList, onTopOfTheQueue );
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addIdGeneratorResolverSecondPass(IdGeneratorResolverSecondPass secondPass, boolean onTopOfTheQueue) {
|
private void addIdGeneratorResolverSecondPass(IdGeneratorResolver secondPass, boolean onTopOfTheQueue) {
|
||||||
if ( idGeneratorResolverSecondPassList == null ) {
|
if ( idGeneratorResolverSecondPassList == null ) {
|
||||||
idGeneratorResolverSecondPassList = new ArrayList<>();
|
idGeneratorResolverSecondPassList = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,6 @@ import jakarta.persistence.Table;
|
||||||
import static org.hibernate.boot.model.internal.AnnotatedClassType.EMBEDDABLE;
|
import static org.hibernate.boot.model.internal.AnnotatedClassType.EMBEDDABLE;
|
||||||
import static org.hibernate.boot.model.internal.AnnotatedClassType.ENTITY;
|
import static org.hibernate.boot.model.internal.AnnotatedClassType.ENTITY;
|
||||||
import static org.hibernate.boot.model.internal.FilterDefBinder.bindFilterDefs;
|
import static org.hibernate.boot.model.internal.FilterDefBinder.bindFilterDefs;
|
||||||
import static org.hibernate.boot.model.internal.GeneratorBinder.buildGenerators;
|
|
||||||
import static org.hibernate.boot.model.internal.GeneratorParameters.interpretSequenceGenerator;
|
import static org.hibernate.boot.model.internal.GeneratorParameters.interpretSequenceGenerator;
|
||||||
import static org.hibernate.boot.model.internal.GeneratorParameters.interpretTableGenerator;
|
import static org.hibernate.boot.model.internal.GeneratorParameters.interpretTableGenerator;
|
||||||
import static org.hibernate.boot.model.internal.InheritanceState.getInheritanceStateOfSuperEntity;
|
import static org.hibernate.boot.model.internal.InheritanceState.getInheritanceStateOfSuperEntity;
|
||||||
|
@ -132,7 +131,7 @@ public final class AnnotationBinder {
|
||||||
sourceContext( context ).getClassDetailsRegistry()
|
sourceContext( context ).getClassDetailsRegistry()
|
||||||
.resolveClassDetails( pack.getName() + ".package-info" );
|
.resolveClassDetails( pack.getName() + ".package-info" );
|
||||||
|
|
||||||
buildGenerators( packageInfoClassDetails, context );
|
GeneratorBinder.registerGlobalGenerators( packageInfoClassDetails, context );
|
||||||
|
|
||||||
bindTypeDescriptorRegistrations( packageInfoClassDetails, context );
|
bindTypeDescriptorRegistrations( packageInfoClassDetails, context );
|
||||||
bindEmbeddableInstantiatorRegistrations( packageInfoClassDetails, context );
|
bindEmbeddableInstantiatorRegistrations( packageInfoClassDetails, context );
|
||||||
|
@ -218,9 +217,9 @@ public final class AnnotationBinder {
|
||||||
bindConverterRegistrations( classDetails, context );
|
bindConverterRegistrations( classDetails, context );
|
||||||
|
|
||||||
// try to find class level generators
|
// try to find class level generators
|
||||||
final Map<String, IdentifierGeneratorDefinition> generators = buildGenerators( classDetails, context );
|
// GeneratorBinder.registerGlobalGenerators( classDetails, context );
|
||||||
if ( context.getMetadataCollector().getClassType( classDetails ) == ENTITY ) {
|
if ( context.getMetadataCollector().getClassType( classDetails ) == ENTITY ) {
|
||||||
EntityBinder.bindEntityClass( classDetails, inheritanceStatePerClass, generators, context );
|
EntityBinder.bindEntityClass( classDetails, inheritanceStatePerClass, context );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -169,7 +169,7 @@ import static org.hibernate.boot.model.internal.BinderHelper.isDefault;
|
||||||
import static org.hibernate.boot.model.internal.BinderHelper.isPrimitive;
|
import static org.hibernate.boot.model.internal.BinderHelper.isPrimitive;
|
||||||
import static org.hibernate.boot.model.internal.DialectOverridesAnnotationHelper.getOverridableAnnotation;
|
import static org.hibernate.boot.model.internal.DialectOverridesAnnotationHelper.getOverridableAnnotation;
|
||||||
import static org.hibernate.boot.model.internal.EmbeddableBinder.fillEmbeddable;
|
import static org.hibernate.boot.model.internal.EmbeddableBinder.fillEmbeddable;
|
||||||
import static org.hibernate.boot.model.internal.GeneratorBinder.buildGenerators;
|
import static org.hibernate.boot.model.internal.GeneratorBinder.visitIdGeneratorDefinitions;
|
||||||
import static org.hibernate.boot.model.internal.PropertyHolderBuilder.buildPropertyHolder;
|
import static org.hibernate.boot.model.internal.PropertyHolderBuilder.buildPropertyHolder;
|
||||||
import static org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle.fromResultCheckStyle;
|
import static org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle.fromResultCheckStyle;
|
||||||
import static org.hibernate.internal.util.ReflectHelper.getDefaultSupplier;
|
import static org.hibernate.internal.util.ReflectHelper.getDefaultSupplier;
|
||||||
|
@ -263,7 +263,6 @@ public abstract class CollectionBinder {
|
||||||
PropertyHolder propertyHolder,
|
PropertyHolder propertyHolder,
|
||||||
Nullability nullability,
|
Nullability nullability,
|
||||||
PropertyData inferredData,
|
PropertyData inferredData,
|
||||||
Map<String, IdentifierGeneratorDefinition> classGenerators,
|
|
||||||
EntityBinder entityBinder,
|
EntityBinder entityBinder,
|
||||||
boolean isIdentifierMapper,
|
boolean isIdentifierMapper,
|
||||||
MetadataBuildingContext context,
|
MetadataBuildingContext context,
|
||||||
|
@ -358,9 +357,26 @@ public abstract class CollectionBinder {
|
||||||
|
|
||||||
if ( property.hasAnnotationUsage( CollectionId.class, sourceModelContext ) ) {
|
if ( property.hasAnnotationUsage( CollectionId.class, sourceModelContext ) ) {
|
||||||
//do not compute the generators unless necessary
|
//do not compute the generators unless necessary
|
||||||
final HashMap<String, IdentifierGeneratorDefinition> localGenerators = new HashMap<>(classGenerators);
|
final HashMap<String, IdentifierGeneratorDefinition> availableGenerators = new HashMap<>();
|
||||||
localGenerators.putAll( buildGenerators( property, context ) );
|
visitIdGeneratorDefinitions(
|
||||||
collectionBinder.setLocalGenerators( localGenerators );
|
property.getDeclaringType(),
|
||||||
|
definition -> {
|
||||||
|
if ( !definition.getName().isEmpty() ) {
|
||||||
|
availableGenerators.put( definition.getName(), definition );
|
||||||
|
}
|
||||||
|
},
|
||||||
|
context
|
||||||
|
);
|
||||||
|
visitIdGeneratorDefinitions(
|
||||||
|
property,
|
||||||
|
definition -> {
|
||||||
|
if ( !definition.getName().isEmpty() ) {
|
||||||
|
availableGenerators.put( definition.getName(), definition );
|
||||||
|
}
|
||||||
|
},
|
||||||
|
context
|
||||||
|
);
|
||||||
|
collectionBinder.setLocalGenerators( availableGenerators );
|
||||||
|
|
||||||
}
|
}
|
||||||
collectionBinder.bind();
|
collectionBinder.bind();
|
||||||
|
|
|
@ -461,7 +461,6 @@ public class EmbeddableBinder {
|
||||||
? Nullability.FORCED_NULL
|
? Nullability.FORCED_NULL
|
||||||
: ( isNullable ? Nullability.NO_CONSTRAINT : Nullability.FORCED_NOT_NULL ),
|
: ( isNullable ? Nullability.NO_CONSTRAINT : Nullability.FORCED_NOT_NULL ),
|
||||||
propertyAnnotatedElement,
|
propertyAnnotatedElement,
|
||||||
Map.of(),
|
|
||||||
entityBinder,
|
entityBinder,
|
||||||
isIdentifierMapper,
|
isIdentifierMapper,
|
||||||
isComponentEmbedded,
|
isComponentEmbedded,
|
||||||
|
@ -480,7 +479,6 @@ public class EmbeddableBinder {
|
||||||
subholder,
|
subholder,
|
||||||
propertyAnnotatedElement,
|
propertyAnnotatedElement,
|
||||||
value,
|
value,
|
||||||
Map.of(),
|
|
||||||
context
|
context
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -213,7 +213,6 @@ public class EntityBinder {
|
||||||
public static void bindEntityClass(
|
public static void bindEntityClass(
|
||||||
ClassDetails clazzToProcess,
|
ClassDetails clazzToProcess,
|
||||||
Map<ClassDetails, InheritanceState> inheritanceStates,
|
Map<ClassDetails, InheritanceState> inheritanceStates,
|
||||||
Map<String, IdentifierGeneratorDefinition> generators,
|
|
||||||
MetadataBuildingContext context) {
|
MetadataBuildingContext context) {
|
||||||
if ( LOG.isDebugEnabled() ) {
|
if ( LOG.isDebugEnabled() ) {
|
||||||
LOG.debugf( "Binding entity from annotated class: %s", clazzToProcess.getName() );
|
LOG.debugf( "Binding entity from annotated class: %s", clazzToProcess.getName() );
|
||||||
|
@ -242,7 +241,7 @@ public class EntityBinder {
|
||||||
inheritanceStates
|
inheritanceStates
|
||||||
);
|
);
|
||||||
entityBinder.handleInheritance( inheritanceState, superEntity, holder );
|
entityBinder.handleInheritance( inheritanceState, superEntity, holder );
|
||||||
entityBinder.handleIdentifier( holder, inheritanceStates, generators, inheritanceState );
|
entityBinder.handleIdentifier( holder, inheritanceStates, inheritanceState );
|
||||||
|
|
||||||
final InFlightMetadataCollector collector = context.getMetadataCollector();
|
final InFlightMetadataCollector collector = context.getMetadataCollector();
|
||||||
if ( persistentClass instanceof RootClass rootClass ) {
|
if ( persistentClass instanceof RootClass rootClass ) {
|
||||||
|
@ -396,7 +395,6 @@ public class EntityBinder {
|
||||||
private void handleIdentifier(
|
private void handleIdentifier(
|
||||||
PropertyHolder propertyHolder,
|
PropertyHolder propertyHolder,
|
||||||
Map<ClassDetails, InheritanceState> inheritanceStates,
|
Map<ClassDetails, InheritanceState> inheritanceStates,
|
||||||
Map<String, IdentifierGeneratorDefinition> generators,
|
|
||||||
InheritanceState inheritanceState) {
|
InheritanceState inheritanceState) {
|
||||||
final ElementsToProcess elementsToProcess = inheritanceState.postProcess( persistentClass, this );
|
final ElementsToProcess elementsToProcess = inheritanceState.postProcess( persistentClass, this );
|
||||||
final Set<String> idPropertiesIfIdClass = handleIdClass(
|
final Set<String> idPropertiesIfIdClass = handleIdClass(
|
||||||
|
@ -412,7 +410,6 @@ public class EntityBinder {
|
||||||
inheritanceState,
|
inheritanceState,
|
||||||
context,
|
context,
|
||||||
propertyHolder,
|
propertyHolder,
|
||||||
generators,
|
|
||||||
idPropertiesIfIdClass,
|
idPropertiesIfIdClass,
|
||||||
elementsToProcess,
|
elementsToProcess,
|
||||||
inheritanceStates
|
inheritanceStates
|
||||||
|
@ -1032,7 +1029,6 @@ public class EntityBinder {
|
||||||
InheritanceState inheritanceState,
|
InheritanceState inheritanceState,
|
||||||
MetadataBuildingContext context,
|
MetadataBuildingContext context,
|
||||||
PropertyHolder propertyHolder,
|
PropertyHolder propertyHolder,
|
||||||
Map<String, IdentifierGeneratorDefinition> generators,
|
|
||||||
Set<String> idPropertiesIfIdClass,
|
Set<String> idPropertiesIfIdClass,
|
||||||
ElementsToProcess elementsToProcess,
|
ElementsToProcess elementsToProcess,
|
||||||
Map<ClassDetails, InheritanceState> inheritanceStates) {
|
Map<ClassDetails, InheritanceState> inheritanceStates) {
|
||||||
|
@ -1063,7 +1059,6 @@ public class EntityBinder {
|
||||||
? Nullability.FORCED_NULL
|
? Nullability.FORCED_NULL
|
||||||
: Nullability.NO_CONSTRAINT,
|
: Nullability.NO_CONSTRAINT,
|
||||||
propertyAnnotatedElement,
|
propertyAnnotatedElement,
|
||||||
generators,
|
|
||||||
this,
|
this,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
|
|
|
@ -0,0 +1,252 @@
|
||||||
|
/*
|
||||||
|
* 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.boot.model.internal;
|
||||||
|
|
||||||
|
import java.lang.annotation.Annotation;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
import org.hibernate.annotations.GenericGenerator;
|
||||||
|
import org.hibernate.annotations.Parameter;
|
||||||
|
import org.hibernate.boot.model.IdentifierGeneratorDefinition;
|
||||||
|
import org.hibernate.boot.models.HibernateAnnotations;
|
||||||
|
import org.hibernate.boot.registry.classloading.spi.ClassLoadingException;
|
||||||
|
import org.hibernate.boot.spi.MetadataBuildingContext;
|
||||||
|
import org.hibernate.generator.Generator;
|
||||||
|
import org.hibernate.id.IdentifierGenerator;
|
||||||
|
import org.hibernate.id.IdentityGenerator;
|
||||||
|
import org.hibernate.id.PersistentIdentifierGenerator;
|
||||||
|
import org.hibernate.id.uuid.UuidGenerator;
|
||||||
|
import org.hibernate.internal.util.StringHelper;
|
||||||
|
import org.hibernate.mapping.PersistentClass;
|
||||||
|
import org.hibernate.mapping.RootClass;
|
||||||
|
import org.hibernate.mapping.SimpleValue;
|
||||||
|
import org.hibernate.models.spi.AnnotationDescriptor;
|
||||||
|
import org.hibernate.models.spi.ClassDetails;
|
||||||
|
import org.hibernate.models.spi.MemberDetails;
|
||||||
|
import org.hibernate.models.spi.SourceModelBuildingContext;
|
||||||
|
|
||||||
|
import jakarta.persistence.SequenceGenerator;
|
||||||
|
import jakarta.persistence.TableGenerator;
|
||||||
|
|
||||||
|
import static org.hibernate.id.IdentifierGenerator.GENERATOR_NAME;
|
||||||
|
import static org.hibernate.internal.util.config.ConfigurationHelper.setIfNotEmpty;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper for dealing with generators defined via annotations
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class GeneratorAnnotationHelper {
|
||||||
|
public static <A extends Annotation> A findLocalizedMatch(
|
||||||
|
AnnotationDescriptor<A> generatorAnnotationType,
|
||||||
|
MemberDetails idMember,
|
||||||
|
Function<A,String> nameExtractor,
|
||||||
|
String matchName,
|
||||||
|
MetadataBuildingContext context) {
|
||||||
|
final SourceModelBuildingContext sourceModelContext = context.getMetadataCollector().getSourceModelBuildingContext();
|
||||||
|
|
||||||
|
A possibleMatch = null;
|
||||||
|
|
||||||
|
// first we look on the member
|
||||||
|
for ( A generatorAnnotation : idMember.getRepeatedAnnotationUsages( generatorAnnotationType, sourceModelContext ) ) {
|
||||||
|
if ( nameExtractor != null ) {
|
||||||
|
final String registrationName = nameExtractor.apply( generatorAnnotation );
|
||||||
|
if ( registrationName.isEmpty() ) {
|
||||||
|
possibleMatch = generatorAnnotation;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( registrationName.equals( matchName ) ) {
|
||||||
|
return generatorAnnotation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return generatorAnnotation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// next, on the class
|
||||||
|
for ( A generatorAnnotation : idMember.getDeclaringType().getRepeatedAnnotationUsages( generatorAnnotationType, sourceModelContext ) ) {
|
||||||
|
if ( nameExtractor != null ) {
|
||||||
|
final String registrationName = nameExtractor.apply( generatorAnnotation );
|
||||||
|
if ( registrationName.isEmpty() ) {
|
||||||
|
if ( possibleMatch == null ) {
|
||||||
|
possibleMatch = generatorAnnotation;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( registrationName.equals( matchName ) ) {
|
||||||
|
return generatorAnnotation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return generatorAnnotation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// lastly, on the package
|
||||||
|
final String packageInfoFqn = StringHelper.qualifier( idMember.getDeclaringType().getClassName() ) + ".package-info";
|
||||||
|
try {
|
||||||
|
final ClassDetails packageInfo = context.getMetadataCollector()
|
||||||
|
.getSourceModelBuildingContext()
|
||||||
|
.getClassDetailsRegistry()
|
||||||
|
.resolveClassDetails( packageInfoFqn );
|
||||||
|
for ( A generatorAnnotation : packageInfo.getRepeatedAnnotationUsages( generatorAnnotationType, sourceModelContext ) ) {
|
||||||
|
if ( nameExtractor != null ) {
|
||||||
|
final String registrationName = nameExtractor.apply( generatorAnnotation );
|
||||||
|
if ( registrationName.isEmpty() ) {
|
||||||
|
if ( possibleMatch == null ) {
|
||||||
|
possibleMatch = generatorAnnotation;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( registrationName.equals( matchName ) ) {
|
||||||
|
return generatorAnnotation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return generatorAnnotation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (ClassLoadingException e) {
|
||||||
|
// means there is no package-info
|
||||||
|
}
|
||||||
|
|
||||||
|
return possibleMatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void handleUuidStrategy(
|
||||||
|
SimpleValue idValue,
|
||||||
|
MemberDetails idMember,
|
||||||
|
MetadataBuildingContext context) {
|
||||||
|
final org.hibernate.annotations.UuidGenerator generatorConfig = findLocalizedMatch(
|
||||||
|
HibernateAnnotations.UUID_GENERATOR,
|
||||||
|
idMember,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
context
|
||||||
|
);
|
||||||
|
idValue.setCustomIdGeneratorCreator( (creationContext) -> new UuidGenerator( generatorConfig, idMember ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void handleIdentityStrategy(
|
||||||
|
SimpleValue idValue,
|
||||||
|
MemberDetails idMember,
|
||||||
|
MetadataBuildingContext context) {
|
||||||
|
idValue.setCustomIdGeneratorCreator( (creationContext) -> new IdentityGenerator() );
|
||||||
|
idValue.setColumnToIdentity();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void applyBaselineConfiguration(
|
||||||
|
SequenceGenerator generatorConfig,
|
||||||
|
SimpleValue idValue,
|
||||||
|
RootClass rootClass,
|
||||||
|
MetadataBuildingContext context,
|
||||||
|
BiConsumer<String,String> configurationCollector) {
|
||||||
|
if ( generatorConfig != null && !generatorConfig.name().isEmpty() ) {
|
||||||
|
configurationCollector.accept( GENERATOR_NAME, generatorConfig.name() );
|
||||||
|
}
|
||||||
|
|
||||||
|
GeneratorParameters.collectParameters(
|
||||||
|
idValue,
|
||||||
|
context.getMetadataCollector().getDatabase().getDialect(),
|
||||||
|
rootClass,
|
||||||
|
configurationCollector
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void applyBaselineConfiguration(
|
||||||
|
TableGenerator generatorConfig,
|
||||||
|
SimpleValue idValue,
|
||||||
|
RootClass rootClass,
|
||||||
|
MetadataBuildingContext context,
|
||||||
|
BiConsumer<String, String> configurationCollector) {
|
||||||
|
if ( !generatorConfig.name().isEmpty() ) {
|
||||||
|
configurationCollector.accept( GENERATOR_NAME, generatorConfig.name() );
|
||||||
|
}
|
||||||
|
|
||||||
|
GeneratorParameters.collectParameters(
|
||||||
|
idValue,
|
||||||
|
context.getMetadataCollector().getDatabase().getDialect(),
|
||||||
|
rootClass,
|
||||||
|
configurationCollector
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void handleGenericGenerator(
|
||||||
|
String generatorName,
|
||||||
|
GenericGenerator generatorConfig,
|
||||||
|
PersistentClass entityMapping,
|
||||||
|
SimpleValue idValue,
|
||||||
|
MemberDetails idMember,
|
||||||
|
MetadataBuildingContext context) {
|
||||||
|
//generator settings
|
||||||
|
final Map<String,String> configuration = new HashMap<>();
|
||||||
|
setIfNotEmpty( generatorConfig.name(), IdentifierGenerator.GENERATOR_NAME, configuration );
|
||||||
|
configuration.put( IdentifierGenerator.ENTITY_NAME, entityMapping.getEntityName() );
|
||||||
|
configuration.put( IdentifierGenerator.JPA_ENTITY_NAME, entityMapping.getJpaEntityName() );
|
||||||
|
|
||||||
|
applyAnnotationParameters( generatorConfig, configuration );
|
||||||
|
|
||||||
|
configuration.put( PersistentIdentifierGenerator.TABLE, idValue.getTable().getName() );
|
||||||
|
if ( idValue.getColumnSpan() == 1 ) {
|
||||||
|
configuration.put( PersistentIdentifierGenerator.PK, idValue.getColumns().get(0).getName() );
|
||||||
|
}
|
||||||
|
|
||||||
|
GeneratorBinder.createGeneratorFrom(
|
||||||
|
new IdentifierGeneratorDefinition( generatorName, determineStrategyName( generatorConfig ), configuration ),
|
||||||
|
idMember,
|
||||||
|
idValue,
|
||||||
|
entityMapping,
|
||||||
|
context
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String determineStrategyName(GenericGenerator generatorConfig) {
|
||||||
|
final Class<? extends Generator> type = generatorConfig.type();
|
||||||
|
if ( !Objects.equals( type, Generator.class ) ) {
|
||||||
|
return type.getName();
|
||||||
|
}
|
||||||
|
return generatorConfig.strategy();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void applyAnnotationParameters(GenericGenerator generatorConfig, Map<String, String> configuration) {
|
||||||
|
for ( Parameter parameter : generatorConfig.parameters() ) {
|
||||||
|
configuration.put( parameter.name(), parameter.value() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void handleTableGenerator(
|
||||||
|
String generatorName,
|
||||||
|
TableGenerator generatorConfig,
|
||||||
|
PersistentClass entityMapping,
|
||||||
|
SimpleValue idValue,
|
||||||
|
MemberDetails idMember,
|
||||||
|
MetadataBuildingContext context) {
|
||||||
|
final Map<String,String> configuration = new HashMap<>();
|
||||||
|
applyBaselineConfiguration( generatorConfig, idValue, entityMapping.getRootClass(), context, configuration::put );
|
||||||
|
org.hibernate.id.enhanced.TableGenerator.applyConfiguration( generatorConfig, idValue, configuration::put );
|
||||||
|
|
||||||
|
GeneratorBinder.createGeneratorFrom(
|
||||||
|
new IdentifierGeneratorDefinition( generatorName, org.hibernate.id.enhanced.TableGenerator.class.getName(), configuration ),
|
||||||
|
idMember,
|
||||||
|
idValue,
|
||||||
|
entityMapping,
|
||||||
|
context
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,11 +6,18 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.boot.model.internal;
|
package org.hibernate.boot.model.internal;
|
||||||
|
|
||||||
import jakarta.persistence.GeneratedValue;
|
import java.lang.annotation.Annotation;
|
||||||
import jakarta.persistence.GenerationType;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import jakarta.persistence.SequenceGenerator;
|
import java.lang.reflect.Member;
|
||||||
import jakarta.persistence.TableGenerator;
|
import java.util.ArrayList;
|
||||||
import jakarta.persistence.Version;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Properties;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import org.hibernate.AnnotationException;
|
import org.hibernate.AnnotationException;
|
||||||
import org.hibernate.AssertionFailure;
|
import org.hibernate.AssertionFailure;
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
|
@ -20,6 +27,7 @@ import org.hibernate.annotations.ValueGenerationType;
|
||||||
import org.hibernate.boot.model.IdentifierGeneratorDefinition;
|
import org.hibernate.boot.model.IdentifierGeneratorDefinition;
|
||||||
import org.hibernate.boot.model.relational.ExportableProducer;
|
import org.hibernate.boot.model.relational.ExportableProducer;
|
||||||
import org.hibernate.boot.model.source.internal.hbm.MappingDocument;
|
import org.hibernate.boot.model.source.internal.hbm.MappingDocument;
|
||||||
|
import org.hibernate.boot.models.spi.GlobalRegistrar;
|
||||||
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.PropertyData;
|
import org.hibernate.boot.spi.PropertyData;
|
||||||
|
@ -33,10 +41,14 @@ import org.hibernate.id.Configurable;
|
||||||
import org.hibernate.id.IdentifierGenerator;
|
import org.hibernate.id.IdentifierGenerator;
|
||||||
import org.hibernate.id.IdentityGenerator;
|
import org.hibernate.id.IdentityGenerator;
|
||||||
import org.hibernate.id.PersistentIdentifierGenerator;
|
import org.hibernate.id.PersistentIdentifierGenerator;
|
||||||
|
import org.hibernate.id.enhanced.SequenceStyleGenerator;
|
||||||
|
import org.hibernate.id.uuid.UuidValueGenerator;
|
||||||
import org.hibernate.internal.CoreLogging;
|
import org.hibernate.internal.CoreLogging;
|
||||||
import org.hibernate.internal.CoreMessageLogger;
|
import org.hibernate.internal.CoreMessageLogger;
|
||||||
|
import org.hibernate.internal.util.StringHelper;
|
||||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||||
import org.hibernate.mapping.GeneratorCreator;
|
import org.hibernate.mapping.GeneratorCreator;
|
||||||
|
import org.hibernate.mapping.PersistentClass;
|
||||||
import org.hibernate.mapping.SimpleValue;
|
import org.hibernate.mapping.SimpleValue;
|
||||||
import org.hibernate.models.spi.AnnotationTarget;
|
import org.hibernate.models.spi.AnnotationTarget;
|
||||||
import org.hibernate.models.spi.MemberDetails;
|
import org.hibernate.models.spi.MemberDetails;
|
||||||
|
@ -46,15 +58,13 @@ import org.hibernate.resource.beans.spi.BeanInstanceProducer;
|
||||||
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 java.lang.annotation.Annotation;
|
import jakarta.persistence.GeneratedValue;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import jakarta.persistence.GenerationType;
|
||||||
import java.lang.reflect.Member;
|
import jakarta.persistence.SequenceGenerator;
|
||||||
import java.util.HashMap;
|
import jakarta.persistence.TableGenerator;
|
||||||
import java.util.List;
|
import jakarta.persistence.Version;
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Properties;
|
|
||||||
|
|
||||||
|
import static jakarta.persistence.GenerationType.AUTO;
|
||||||
import static java.util.Collections.emptyMap;
|
import static java.util.Collections.emptyMap;
|
||||||
import static org.hibernate.boot.model.internal.AnnotationHelper.extractParameterMap;
|
import static org.hibernate.boot.model.internal.AnnotationHelper.extractParameterMap;
|
||||||
import static org.hibernate.boot.model.internal.BinderHelper.getPath;
|
import static org.hibernate.boot.model.internal.BinderHelper.getPath;
|
||||||
|
@ -63,7 +73,7 @@ import static org.hibernate.boot.model.internal.GeneratorParameters.collectParam
|
||||||
import static org.hibernate.boot.model.internal.GeneratorParameters.interpretSequenceGenerator;
|
import static org.hibernate.boot.model.internal.GeneratorParameters.interpretSequenceGenerator;
|
||||||
import static org.hibernate.boot.model.internal.GeneratorParameters.interpretTableGenerator;
|
import static org.hibernate.boot.model.internal.GeneratorParameters.interpretTableGenerator;
|
||||||
import static org.hibernate.boot.model.internal.GeneratorStrategies.generatorClass;
|
import static org.hibernate.boot.model.internal.GeneratorStrategies.generatorClass;
|
||||||
import static org.hibernate.boot.model.internal.GeneratorStrategies.generatorStrategy;
|
import static org.hibernate.id.IdentifierGenerator.GENERATOR_NAME;
|
||||||
import static org.hibernate.internal.util.NullnessUtil.castNonNull;
|
import static org.hibernate.internal.util.NullnessUtil.castNonNull;
|
||||||
import static org.hibernate.internal.util.StringHelper.qualify;
|
import static org.hibernate.internal.util.StringHelper.qualify;
|
||||||
import static org.hibernate.resource.beans.internal.Helper.allowExtensionsInCdi;
|
import static org.hibernate.resource.beans.internal.Helper.allowExtensionsInCdi;
|
||||||
|
@ -94,7 +104,7 @@ public class GeneratorBinder {
|
||||||
* Create a generator, based on a {@link GeneratedValue} annotation.
|
* Create a generator, based on a {@link GeneratedValue} annotation.
|
||||||
*/
|
*/
|
||||||
public static void makeIdGenerator(
|
public static void makeIdGenerator(
|
||||||
SimpleValue id,
|
SimpleValue identifierValue,
|
||||||
MemberDetails idAttributeMember,
|
MemberDetails idAttributeMember,
|
||||||
String generatorType,
|
String generatorType,
|
||||||
String generatorName,
|
String generatorName,
|
||||||
|
@ -103,15 +113,105 @@ public class GeneratorBinder {
|
||||||
|
|
||||||
//generator settings
|
//generator settings
|
||||||
final Map<String,Object> configuration = new HashMap<>();
|
final Map<String,Object> configuration = new HashMap<>();
|
||||||
configuration.put( IdentifierGenerator.GENERATOR_NAME, generatorName );
|
configuration.put( GENERATOR_NAME, generatorName );
|
||||||
configuration.put( PersistentIdentifierGenerator.TABLE, id.getTable().getName() );
|
configuration.put( PersistentIdentifierGenerator.TABLE, identifierValue.getTable().getName() );
|
||||||
if ( id.getColumnSpan() == 1 ) {
|
if ( identifierValue.getColumnSpan() == 1 ) {
|
||||||
configuration.put( PersistentIdentifierGenerator.PK, id.getColumns().get(0).getName() );
|
configuration.put( PersistentIdentifierGenerator.PK, identifierValue.getColumns().get(0).getName() );
|
||||||
}
|
}
|
||||||
|
|
||||||
final String generatorStrategy =
|
if ( generatorName.isEmpty() ) {
|
||||||
determineStrategy( idAttributeMember, generatorType, generatorName, context, localGenerators, configuration );
|
final GeneratedValue generatedValue = idAttributeMember.getDirectAnnotationUsage( GeneratedValue.class );
|
||||||
setGeneratorCreator( id, configuration, generatorStrategy, context );
|
if ( generatedValue != null ) {
|
||||||
|
// The mapping used @GeneratedValue but specified no name. This is a special case added in JPA 3.2.
|
||||||
|
// Look for a matching "implied generator" based on the GenerationType
|
||||||
|
|
||||||
|
final GenerationType strategy = generatedValue.strategy();
|
||||||
|
final String strategyGeneratorClassName = correspondingGeneratorName( strategy );
|
||||||
|
|
||||||
|
final IdentifierGeneratorDefinition impliedGenerator = determineImpliedGenerator(
|
||||||
|
strategy,
|
||||||
|
strategyGeneratorClassName,
|
||||||
|
localGenerators
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( impliedGenerator != null ) {
|
||||||
|
configuration.putAll( impliedGenerator.getParameters() );
|
||||||
|
|
||||||
|
final BeanContainer beanContainer = beanContainer( context );
|
||||||
|
identifierValue.setCustomIdGeneratorCreator( creationContext -> {
|
||||||
|
final Generator identifierGenerator = instantiateGenerator(
|
||||||
|
beanContainer,
|
||||||
|
generatorClass( strategyGeneratorClassName, identifierValue )
|
||||||
|
);
|
||||||
|
callConfigure( creationContext, identifierGenerator, configuration, identifierValue );
|
||||||
|
if ( identifierGenerator instanceof IdentityGenerator) {
|
||||||
|
identifierValue.setColumnToIdentity();
|
||||||
|
}
|
||||||
|
return identifierGenerator;
|
||||||
|
} );
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final String generatorStrategy = determineStrategy(
|
||||||
|
idAttributeMember,
|
||||||
|
generatorType,
|
||||||
|
generatorName,
|
||||||
|
context,
|
||||||
|
localGenerators,
|
||||||
|
configuration
|
||||||
|
);
|
||||||
|
setGeneratorCreator( identifierValue, configuration, generatorStrategy, context );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IdentifierGeneratorDefinition determineImpliedGenerator(
|
||||||
|
GenerationType strategy,
|
||||||
|
String strategyGeneratorClassName,
|
||||||
|
Map<String, ? extends IdentifierGeneratorDefinition> localGenerators) {
|
||||||
|
if ( localGenerators == null ) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( localGenerators.size() == 1 ) {
|
||||||
|
final IdentifierGeneratorDefinition generatorDefinition = localGenerators.entrySet().iterator().next().getValue();
|
||||||
|
// NOTE : a little bit of a special rule here for the case of just one -
|
||||||
|
// we consider it a match, based on strategy, if the strategy is AUTO or matches...
|
||||||
|
if ( strategy == AUTO
|
||||||
|
|| isImpliedGenerator( strategy, strategyGeneratorClassName, generatorDefinition ) ) {
|
||||||
|
return generatorDefinition;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IdentifierGeneratorDefinition matching = null;
|
||||||
|
for ( Map.Entry<String, ? extends IdentifierGeneratorDefinition> localGeneratorEntry : localGenerators.entrySet() ) {
|
||||||
|
if ( isImpliedGenerator( strategy, strategyGeneratorClassName, localGeneratorEntry.getValue() ) ) {
|
||||||
|
if ( matching != null ) {
|
||||||
|
// we found multiple matching generators
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
matching = localGeneratorEntry.getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return matching;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isImpliedGenerator(
|
||||||
|
GenerationType strategy,
|
||||||
|
String strategyGeneratorClassName,
|
||||||
|
IdentifierGeneratorDefinition generatorDefinition) {
|
||||||
|
return generatorDefinition.getStrategy().equals( strategyGeneratorClassName );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String correspondingGeneratorName(GenerationType strategy) {
|
||||||
|
return switch ( strategy ) {
|
||||||
|
// case UUID -> org.hibernate.id.uuid.UuidGenerator.class.getName();
|
||||||
|
case UUID -> UuidValueGenerator.class.getName();
|
||||||
|
case TABLE -> org.hibernate.id.enhanced.TableGenerator.class.getName();
|
||||||
|
case IDENTITY -> null;
|
||||||
|
default -> SequenceStyleGenerator.class.getName();
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String determineStrategy(
|
private static String determineStrategy(
|
||||||
|
@ -182,39 +282,66 @@ public class GeneratorBinder {
|
||||||
private static GenerationType interpretGenerationType(GeneratedValue generatedValueAnn) {
|
private static GenerationType interpretGenerationType(GeneratedValue generatedValueAnn) {
|
||||||
// todo (jpa32) : when can this ever be null?
|
// todo (jpa32) : when can this ever be null?
|
||||||
final GenerationType strategy = generatedValueAnn.strategy();
|
final GenerationType strategy = generatedValueAnn.strategy();
|
||||||
return strategy == null ? GenerationType.AUTO : strategy;
|
return strategy == null ? AUTO : strategy;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build any generators declared using {@link TableGenerator}, {@link SequenceGenerator},
|
* Collects definition objects for all generators defined using any of {@link TableGenerator},
|
||||||
* and {@link GenericGenerator} annotations of the given program element.
|
* {@link SequenceGenerator}, and {@link GenericGenerator} on the given annotated element.
|
||||||
*/
|
*/
|
||||||
public static Map<String, IdentifierGeneratorDefinition> buildGenerators(
|
public static List<IdentifierGeneratorDefinition> collectIdGeneratorDefinitions(
|
||||||
AnnotationTarget annotatedElement,
|
AnnotationTarget annotatedElement,
|
||||||
MetadataBuildingContext context) {
|
MetadataBuildingContext context) {
|
||||||
|
final ArrayList<IdentifierGeneratorDefinition> definitions = new ArrayList<>();
|
||||||
|
visitIdGeneratorDefinitions(
|
||||||
|
annotatedElement,
|
||||||
|
definitions::add,
|
||||||
|
context
|
||||||
|
);
|
||||||
|
return definitions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void visitIdGeneratorDefinitions(
|
||||||
|
AnnotationTarget annotatedElement,
|
||||||
|
Consumer<IdentifierGeneratorDefinition> consumer,
|
||||||
|
MetadataBuildingContext context) {
|
||||||
final InFlightMetadataCollector metadataCollector = context.getMetadataCollector();
|
final InFlightMetadataCollector metadataCollector = context.getMetadataCollector();
|
||||||
final SourceModelBuildingContext sourceModelContext = metadataCollector.getSourceModelBuildingContext();
|
final SourceModelBuildingContext sourceModelContext = metadataCollector.getSourceModelBuildingContext();
|
||||||
final Map<String, IdentifierGeneratorDefinition> generators = new HashMap<>();
|
|
||||||
|
|
||||||
annotatedElement.forEachAnnotationUsage( TableGenerator.class, sourceModelContext, (usage) -> {
|
annotatedElement.forEachAnnotationUsage( TableGenerator.class, sourceModelContext, (usage) -> {
|
||||||
IdentifierGeneratorDefinition idGenerator = buildTableIdGenerator( usage );
|
final IdentifierGeneratorDefinition idGenerator = buildTableIdGenerator( usage );
|
||||||
generators.put( idGenerator.getName(), idGenerator );
|
consumer.accept( idGenerator );
|
||||||
metadataCollector.addIdentifierGenerator( idGenerator );
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
annotatedElement.forEachAnnotationUsage( SequenceGenerator.class, sourceModelContext, (usage) -> {
|
annotatedElement.forEachAnnotationUsage( SequenceGenerator.class, sourceModelContext, (usage) -> {
|
||||||
IdentifierGeneratorDefinition idGenerator = buildSequenceIdGenerator( usage );
|
final IdentifierGeneratorDefinition idGenerator = buildSequenceIdGenerator( usage );
|
||||||
generators.put( idGenerator.getName(), idGenerator );
|
consumer.accept( idGenerator );
|
||||||
metadataCollector.addIdentifierGenerator( idGenerator );
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
annotatedElement.forEachAnnotationUsage( GenericGenerator.class, sourceModelContext, (usage) -> {
|
annotatedElement.forEachAnnotationUsage( GenericGenerator.class, sourceModelContext, (usage) -> {
|
||||||
final IdentifierGeneratorDefinition idGenerator = buildIdGenerator( usage );
|
final IdentifierGeneratorDefinition idGenerator = buildIdGenerator( usage );
|
||||||
generators.put( idGenerator.getName(), idGenerator );
|
consumer.accept( idGenerator );
|
||||||
metadataCollector.addIdentifierGenerator( idGenerator );
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
return generators;
|
}
|
||||||
|
|
||||||
|
public static void registerGlobalGenerators(
|
||||||
|
AnnotationTarget annotatedElement,
|
||||||
|
MetadataBuildingContext context) {
|
||||||
|
if ( !context.getBootstrapContext().getJpaCompliance().isGlobalGeneratorScopeEnabled() ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final InFlightMetadataCollector metadataCollector = context.getMetadataCollector();
|
||||||
|
visitIdGeneratorDefinitions(
|
||||||
|
annotatedElement,
|
||||||
|
(definition) -> {
|
||||||
|
if ( !definition.getName().isEmpty() ) {
|
||||||
|
metadataCollector.addIdentifierGenerator( definition );
|
||||||
|
}
|
||||||
|
},
|
||||||
|
context
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IdentifierGeneratorDefinition buildIdGenerator(GenericGenerator generatorAnnotation) {
|
private static IdentifierGeneratorDefinition buildIdGenerator(GenericGenerator generatorAnnotation) {
|
||||||
|
@ -502,7 +629,7 @@ public class GeneratorBinder {
|
||||||
* @param beanContainer an optional {@code BeanContainer}
|
* @param beanContainer an optional {@code BeanContainer}
|
||||||
* @param generatorClass a class which implements {@code Generator}
|
* @param generatorClass a class which implements {@code Generator}
|
||||||
*/
|
*/
|
||||||
private static Generator instantiateGenerator(
|
public static Generator instantiateGenerator(
|
||||||
BeanContainer beanContainer,
|
BeanContainer beanContainer,
|
||||||
Class<? extends Generator> generatorClass) {
|
Class<? extends Generator> generatorClass) {
|
||||||
if ( beanContainer != null ) {
|
if ( beanContainer != null ) {
|
||||||
|
@ -563,7 +690,7 @@ public class GeneratorBinder {
|
||||||
* call its {@link Configurable#configure(GeneratorCreationContext, Properties)
|
* call its {@link Configurable#configure(GeneratorCreationContext, Properties)
|
||||||
* configure()} method.
|
* configure()} method.
|
||||||
*/
|
*/
|
||||||
private static void callConfigure(
|
public static void callConfigure(
|
||||||
GeneratorCreationContext creationContext,
|
GeneratorCreationContext creationContext,
|
||||||
Generator generator,
|
Generator generator,
|
||||||
Map<String, Object> configuration,
|
Map<String, Object> configuration,
|
||||||
|
@ -594,35 +721,93 @@ public class GeneratorBinder {
|
||||||
* Create a generator, based on a {@link GeneratedValue} annotation.
|
* Create a generator, based on a {@link GeneratedValue} annotation.
|
||||||
*/
|
*/
|
||||||
private static void createIdGenerator(
|
private static void createIdGenerator(
|
||||||
|
MemberDetails idMember,
|
||||||
SimpleValue idValue,
|
SimpleValue idValue,
|
||||||
Map<String, IdentifierGeneratorDefinition> classGenerators,
|
PersistentClass persistentClass,
|
||||||
MetadataBuildingContext context,
|
MetadataBuildingContext context) {
|
||||||
MemberDetails idMember) {
|
// NOTE: `generatedValue` is never null here
|
||||||
//manage composite related metadata
|
|
||||||
//guess if its a component and find id data access (property, field etc)
|
|
||||||
final GeneratedValue generatedValue = castNonNull( idMember.getDirectAnnotationUsage( GeneratedValue.class ) );
|
final GeneratedValue generatedValue = castNonNull( idMember.getDirectAnnotationUsage( GeneratedValue.class ) );
|
||||||
final String generatorType =
|
|
||||||
generatorStrategy( generatedValue.strategy(), generatedValue.generator(), idMember.getType() );
|
|
||||||
final String generatorName = generatedValue.generator();
|
|
||||||
if ( isGlobalGeneratorNameGlobal( context ) ) {
|
if ( isGlobalGeneratorNameGlobal( context ) ) {
|
||||||
buildGenerators( idMember, context );
|
// process and register any generators defined on the member.
|
||||||
context.getMetadataCollector()
|
// according to JPA these are also global.
|
||||||
.addSecondPass( new IdGeneratorResolverSecondPass(
|
context.getMetadataCollector().getGlobalRegistrations().as( GlobalRegistrar.class ).collectIdGenerators( idMember );
|
||||||
|
context.getMetadataCollector().addSecondPass( new StrictIdGeneratorResolverSecondPass(
|
||||||
|
persistentClass,
|
||||||
idValue,
|
idValue,
|
||||||
idMember,
|
idMember,
|
||||||
generatorType,
|
|
||||||
generatorName,
|
|
||||||
context
|
context
|
||||||
) );
|
) );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
//clone classGenerator and override with local values
|
context.getMetadataCollector().addSecondPass( new IdGeneratorResolverSecondPass(
|
||||||
final Map<String, IdentifierGeneratorDefinition> generators = new HashMap<>( classGenerators );
|
persistentClass,
|
||||||
generators.putAll( buildGenerators( idMember, context ) );
|
idValue,
|
||||||
makeIdGenerator( idValue, idMember, generatorType, generatorName, context, generators );
|
idMember,
|
||||||
|
generatedValue,
|
||||||
|
context
|
||||||
|
) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void createGeneratorFrom(
|
||||||
|
IdentifierGeneratorDefinition defaultedGenerator,
|
||||||
|
MemberDetails idMember,
|
||||||
|
SimpleValue idValue,
|
||||||
|
Map<String, Object> configuration,
|
||||||
|
MetadataBuildingContext context) {
|
||||||
|
configuration.putAll( defaultedGenerator.getParameters() );
|
||||||
|
|
||||||
|
final BeanContainer beanContainer = beanContainer( context );
|
||||||
|
idValue.setCustomIdGeneratorCreator( creationContext -> {
|
||||||
|
final Generator identifierGenerator = instantiateGenerator(
|
||||||
|
beanContainer,
|
||||||
|
generatorClass( defaultedGenerator.getStrategy(), idValue )
|
||||||
|
);
|
||||||
|
callConfigure( creationContext, identifierGenerator, configuration, idValue );
|
||||||
|
if ( identifierGenerator instanceof IdentityGenerator) {
|
||||||
|
idValue.setColumnToIdentity();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( identifierGenerator instanceof ExportableProducer exportableProducer ) {
|
||||||
|
exportableProducer.registerExportables( creationContext.getDatabase() );
|
||||||
|
}
|
||||||
|
|
||||||
|
return identifierGenerator;
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void createGeneratorFrom(
|
||||||
|
IdentifierGeneratorDefinition defaultedGenerator,
|
||||||
|
MemberDetails idMember,
|
||||||
|
SimpleValue idValue,
|
||||||
|
PersistentClass persistentClass,
|
||||||
|
MetadataBuildingContext context) {
|
||||||
|
createGeneratorFrom(
|
||||||
|
defaultedGenerator,
|
||||||
|
idMember,
|
||||||
|
idValue,
|
||||||
|
buildConfigurationMap( defaultedGenerator, idValue, persistentClass ),
|
||||||
|
context
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Map<String, Object> buildConfigurationMap(
|
||||||
|
IdentifierGeneratorDefinition defaultedGenerator,
|
||||||
|
SimpleValue idValue,
|
||||||
|
PersistentClass persistentClass) {
|
||||||
|
final Map<String,Object> configuration = new HashMap<>();
|
||||||
|
|
||||||
|
configuration.put( PersistentIdentifierGenerator.TABLE, idValue.getTable().getName() );
|
||||||
|
|
||||||
|
if ( idValue.getColumnSpan() == 1 ) {
|
||||||
|
configuration.put( PersistentIdentifierGenerator.PK, idValue.getColumns().get( 0).getName() );
|
||||||
|
}
|
||||||
|
|
||||||
|
return configuration;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set up the identifier generator for an id defined in a {@code hbm.xml} mapping.
|
* Set up the identifier generator for an id defined in a {@code hbm.xml} mapping.
|
||||||
*
|
*
|
||||||
|
@ -658,7 +843,7 @@ public class GeneratorBinder {
|
||||||
/**
|
/**
|
||||||
* Obtain a {@link BeanContainer} to be used for instantiating generators.
|
* Obtain a {@link BeanContainer} to be used for instantiating generators.
|
||||||
*/
|
*/
|
||||||
private static BeanContainer beanContainer(MetadataBuildingContext buildingContext) {
|
public static BeanContainer beanContainer(MetadataBuildingContext buildingContext) {
|
||||||
final ServiceRegistry serviceRegistry = buildingContext.getBootstrapContext().getServiceRegistry();
|
final ServiceRegistry serviceRegistry = buildingContext.getBootstrapContext().getServiceRegistry();
|
||||||
return allowExtensionsInCdi( serviceRegistry )
|
return allowExtensionsInCdi( serviceRegistry )
|
||||||
? serviceRegistry.requireService( ManagedBeanRegistry.class ).getBeanContainer()
|
? serviceRegistry.requireService( ManagedBeanRegistry.class ).getBeanContainer()
|
||||||
|
@ -701,7 +886,6 @@ public class GeneratorBinder {
|
||||||
PropertyHolder propertyHolder,
|
PropertyHolder propertyHolder,
|
||||||
PropertyData inferredData,
|
PropertyData inferredData,
|
||||||
SimpleValue idValue,
|
SimpleValue idValue,
|
||||||
Map<String, IdentifierGeneratorDefinition> classGenerators,
|
|
||||||
MetadataBuildingContext context) {
|
MetadataBuildingContext context) {
|
||||||
|
|
||||||
final SourceModelBuildingContext sourceModelContext =
|
final SourceModelBuildingContext sourceModelContext =
|
||||||
|
@ -745,7 +929,7 @@ public class GeneratorBinder {
|
||||||
) );
|
) );
|
||||||
}
|
}
|
||||||
else if ( idAttributeMember.hasDirectAnnotationUsage( GeneratedValue.class ) ) {
|
else if ( idAttributeMember.hasDirectAnnotationUsage( GeneratedValue.class ) ) {
|
||||||
createIdGenerator( idValue, classGenerators, context, idAttributeMember );
|
createIdGenerator( idAttributeMember, idValue, propertyHolder.getPersistentClass(), context );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -769,4 +953,10 @@ public class GeneratorBinder {
|
||||||
+ "' has too many generator annotations: " + generatorAnnotations );
|
+ "' has too many generator annotations: " + generatorAnnotations );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void applyIfNotEmpty(String name, String value, BiConsumer<String,String> consumer) {
|
||||||
|
if ( StringHelper.isNotEmpty( value ) ) {
|
||||||
|
consumer.accept( name, value );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,8 @@ import jakarta.persistence.TableGenerator;
|
||||||
import jakarta.persistence.UniqueConstraint;
|
import jakarta.persistence.UniqueConstraint;
|
||||||
import org.hibernate.Internal;
|
import org.hibernate.Internal;
|
||||||
import org.hibernate.boot.model.IdentifierGeneratorDefinition;
|
import org.hibernate.boot.model.IdentifierGeneratorDefinition;
|
||||||
|
import org.hibernate.boot.spi.MetadataBuildingContext;
|
||||||
|
import org.hibernate.boot.spi.MetadataImplementor;
|
||||||
import org.hibernate.cfg.AvailableSettings;
|
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.ConfigurationService;
|
||||||
|
@ -36,6 +38,18 @@ import org.hibernate.type.Type;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
|
||||||
|
import static org.hibernate.id.IdentifierGenerator.CONTRIBUTOR_NAME;
|
||||||
|
import static org.hibernate.id.IdentifierGenerator.ENTITY_NAME;
|
||||||
|
import static org.hibernate.id.IdentifierGenerator.JPA_ENTITY_NAME;
|
||||||
|
import static org.hibernate.id.OptimizableGenerator.DEFAULT_INITIAL_VALUE;
|
||||||
|
import static org.hibernate.id.OptimizableGenerator.IMPLICIT_NAME_BASE;
|
||||||
|
import static org.hibernate.id.OptimizableGenerator.INCREMENT_PARAM;
|
||||||
|
import static org.hibernate.id.OptimizableGenerator.INITIAL_PARAM;
|
||||||
|
import static org.hibernate.id.PersistentIdentifierGenerator.PK;
|
||||||
|
import static org.hibernate.id.PersistentIdentifierGenerator.TABLE;
|
||||||
|
import static org.hibernate.id.PersistentIdentifierGenerator.TABLES;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Responsible for setting up the parameters which are passed to
|
* Responsible for setting up the parameters which are passed to
|
||||||
|
@ -50,6 +64,19 @@ public class GeneratorParameters {
|
||||||
|
|
||||||
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( GeneratorBinder.class );
|
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( GeneratorBinder.class );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Collect the parameters which should be passed to
|
||||||
|
* {@link Configurable#configure(GeneratorCreationContext, Properties)}.
|
||||||
|
*/
|
||||||
|
public static Properties collectParameters(
|
||||||
|
SimpleValue identifierValue,
|
||||||
|
Dialect dialect,
|
||||||
|
RootClass rootClass) {
|
||||||
|
final Properties params = new Properties();
|
||||||
|
collectParameters( identifierValue, dialect, rootClass, params::put );
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Collect the parameters which should be passed to
|
* Collect the parameters which should be passed to
|
||||||
* {@link Configurable#configure(GeneratorCreationContext, Properties)}.
|
* {@link Configurable#configure(GeneratorCreationContext, Properties)}.
|
||||||
|
@ -59,63 +86,73 @@ public class GeneratorParameters {
|
||||||
Dialect dialect,
|
Dialect dialect,
|
||||||
RootClass rootClass,
|
RootClass rootClass,
|
||||||
Map<String, Object> configuration) {
|
Map<String, Object> configuration) {
|
||||||
|
final Properties params = collectParameters( identifierValue, dialect, rootClass );
|
||||||
|
if ( configuration != null ) {
|
||||||
|
params.putAll( configuration );
|
||||||
|
}
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void collectParameters(
|
||||||
|
SimpleValue identifierValue,
|
||||||
|
Dialect dialect,
|
||||||
|
RootClass rootClass,
|
||||||
|
BiConsumer<String,String> parameterCollector) {
|
||||||
|
|
||||||
final ConfigurationService configService =
|
final ConfigurationService configService =
|
||||||
identifierValue.getMetadata().getMetadataBuildingOptions().getServiceRegistry()
|
identifierValue.getMetadata().getMetadataBuildingOptions().getServiceRegistry()
|
||||||
.requireService( ConfigurationService.class );
|
.requireService( ConfigurationService.class );
|
||||||
|
|
||||||
final Properties params = new Properties();
|
|
||||||
|
|
||||||
// default initial value and allocation size per-JPA defaults
|
// default initial value and allocation size per-JPA defaults
|
||||||
params.setProperty( OptimizableGenerator.INITIAL_PARAM,
|
parameterCollector.accept( INITIAL_PARAM, String.valueOf( DEFAULT_INITIAL_VALUE ) );
|
||||||
String.valueOf( OptimizableGenerator.DEFAULT_INITIAL_VALUE ) );
|
parameterCollector.accept( INCREMENT_PARAM, String.valueOf( defaultIncrement( configService ) ) );
|
||||||
|
|
||||||
params.setProperty( OptimizableGenerator.INCREMENT_PARAM,
|
|
||||||
String.valueOf( defaultIncrement( configService ) ) );
|
|
||||||
//init the table here instead of earlier, so that we can get a quoted table name
|
//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
|
//TODO: would it be better to simply pass the qualified table name, instead of
|
||||||
// splitting it up into schema/catalog/table names
|
// splitting it up into schema/catalog/table names
|
||||||
final String tableName = identifierValue.getTable().getQuotedName( dialect );
|
final String tableName = identifierValue.getTable().getQuotedName( dialect );
|
||||||
params.setProperty( PersistentIdentifierGenerator.TABLE, tableName );
|
parameterCollector.accept( TABLE, tableName );
|
||||||
|
|
||||||
//pass the column name (a generated id almost always has a single column)
|
//pass the column name (a generated id almost always has a single column)
|
||||||
|
if ( identifierValue.getColumnSpan() == 1 ) {
|
||||||
final Column column = (Column) identifierValue.getSelectables().get( 0 );
|
final Column column = (Column) identifierValue.getSelectables().get( 0 );
|
||||||
final String columnName = column.getQuotedName( dialect );
|
final String columnName = column.getQuotedName( dialect );
|
||||||
params.setProperty( PersistentIdentifierGenerator.PK, columnName );
|
parameterCollector.accept( PK, columnName );
|
||||||
|
}
|
||||||
|
|
||||||
//pass the entity-name, if not a collection-id
|
//pass the entity-name, if not a collection-id
|
||||||
if ( rootClass != null ) {
|
if ( rootClass != null ) {
|
||||||
params.setProperty( IdentifierGenerator.ENTITY_NAME, rootClass.getEntityName() );
|
parameterCollector.accept( ENTITY_NAME, rootClass.getEntityName() );
|
||||||
params.setProperty( IdentifierGenerator.JPA_ENTITY_NAME, rootClass.getJpaEntityName() );
|
parameterCollector.accept( JPA_ENTITY_NAME, rootClass.getJpaEntityName() );
|
||||||
// The table name is not really a good default for subselect entities,
|
// The table name is not really a good default for subselect entities,
|
||||||
// so use the JPA entity name which is short
|
// so use the JPA entity name which is short
|
||||||
params.setProperty( OptimizableGenerator.IMPLICIT_NAME_BASE,
|
parameterCollector.accept(
|
||||||
|
IMPLICIT_NAME_BASE,
|
||||||
identifierValue.getTable().isSubselect()
|
identifierValue.getTable().isSubselect()
|
||||||
? rootClass.getJpaEntityName()
|
? rootClass.getJpaEntityName()
|
||||||
: identifierValue.getTable().getName() );
|
: identifierValue.getTable().getName()
|
||||||
|
);
|
||||||
|
|
||||||
params.setProperty( PersistentIdentifierGenerator.TABLES,
|
parameterCollector.accept( TABLES, identityTablesString( dialect, rootClass ) );
|
||||||
identityTablesString( dialect, rootClass ) );
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
params.setProperty( PersistentIdentifierGenerator.TABLES, tableName );
|
parameterCollector.accept( TABLES, tableName );
|
||||||
params.setProperty( OptimizableGenerator.IMPLICIT_NAME_BASE, tableName );
|
parameterCollector.accept( IMPLICIT_NAME_BASE, tableName );
|
||||||
}
|
}
|
||||||
|
|
||||||
params.put( IdentifierGenerator.CONTRIBUTOR_NAME,
|
parameterCollector.accept( CONTRIBUTOR_NAME, identifierValue.getBuildingContext().getCurrentContributorName() );
|
||||||
identifierValue.getBuildingContext().getCurrentContributorName() );
|
|
||||||
|
|
||||||
final Map<String, Object> settings = configService.getSettings();
|
final Map<String, Object> settings = configService.getSettings();
|
||||||
if ( settings.containsKey( AvailableSettings.PREFERRED_POOLED_OPTIMIZER ) ) {
|
if ( settings.containsKey( AvailableSettings.PREFERRED_POOLED_OPTIMIZER ) ) {
|
||||||
params.put( AvailableSettings.PREFERRED_POOLED_OPTIMIZER,
|
parameterCollector.accept(
|
||||||
settings.get( AvailableSettings.PREFERRED_POOLED_OPTIMIZER ) );
|
AvailableSettings.PREFERRED_POOLED_OPTIMIZER,
|
||||||
|
(String) settings.get( AvailableSettings.PREFERRED_POOLED_OPTIMIZER )
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
params.putAll( configuration );
|
public static String identityTablesString(Dialect dialect, RootClass rootClass) {
|
||||||
|
|
||||||
return params;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String identityTablesString(Dialect dialect, RootClass rootClass) {
|
|
||||||
final StringBuilder tables = new StringBuilder();
|
final StringBuilder tables = new StringBuilder();
|
||||||
for ( Table table : rootClass.getIdentityTables() ) {
|
for ( Table table : rootClass.getIdentityTables() ) {
|
||||||
tables.append( table.getQuotedName( dialect ) );
|
tables.append( table.getQuotedName( dialect ) );
|
||||||
|
@ -126,7 +163,11 @@ public class GeneratorParameters {
|
||||||
return tables.toString();
|
return tables.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int defaultIncrement(ConfigurationService configService) {
|
public static int defaultIncrement(MetadataImplementor metadata) {
|
||||||
|
return defaultIncrement( metadata.getMetadataBuildingOptions().getServiceRegistry().requireService( ConfigurationService.class ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int defaultIncrement(ConfigurationService configService) {
|
||||||
final String idNamingStrategy =
|
final String idNamingStrategy =
|
||||||
configService.getSetting( AvailableSettings.ID_DB_STRUCTURE_NAMING_STRATEGY,
|
configService.getSetting( AvailableSettings.ID_DB_STRUCTURE_NAMING_STRATEGY,
|
||||||
StandardConverters.STRING, null );
|
StandardConverters.STRING, null );
|
||||||
|
@ -198,13 +239,13 @@ public class GeneratorParameters {
|
||||||
}
|
}
|
||||||
|
|
||||||
definitionBuilder.addParam(
|
definitionBuilder.addParam(
|
||||||
org.hibernate.id.enhanced.TableGenerator.INCREMENT_PARAM,
|
INCREMENT_PARAM,
|
||||||
String.valueOf( tableGeneratorAnnotation.allocationSize() )
|
String.valueOf( tableGeneratorAnnotation.allocationSize() )
|
||||||
);
|
);
|
||||||
|
|
||||||
// See comment on HHH-4884 wrt initialValue. Basically initialValue is really the stated value + 1
|
// See comment on HHH-4884 wrt initialValue. Basically initialValue is really the stated value + 1
|
||||||
definitionBuilder.addParam(
|
definitionBuilder.addParam(
|
||||||
org.hibernate.id.enhanced.TableGenerator.INITIAL_PARAM,
|
INITIAL_PARAM,
|
||||||
String.valueOf( tableGeneratorAnnotation.initialValue() + 1 )
|
String.valueOf( tableGeneratorAnnotation.initialValue() + 1 )
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -238,11 +279,11 @@ public class GeneratorParameters {
|
||||||
}
|
}
|
||||||
|
|
||||||
definitionBuilder.addParam(
|
definitionBuilder.addParam(
|
||||||
SequenceStyleGenerator.INCREMENT_PARAM,
|
INCREMENT_PARAM,
|
||||||
String.valueOf( sequenceGeneratorAnnotation.allocationSize() )
|
String.valueOf( sequenceGeneratorAnnotation.allocationSize() )
|
||||||
);
|
);
|
||||||
definitionBuilder.addParam(
|
definitionBuilder.addParam(
|
||||||
SequenceStyleGenerator.INITIAL_PARAM,
|
INITIAL_PARAM,
|
||||||
String.valueOf( sequenceGeneratorAnnotation.initialValue() )
|
String.valueOf( sequenceGeneratorAnnotation.initialValue() )
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,8 @@ package org.hibernate.boot.model.internal;
|
||||||
import jakarta.persistence.GenerationType;
|
import jakarta.persistence.GenerationType;
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||||
|
import org.hibernate.boot.spi.MetadataBuildingContext;
|
||||||
|
import org.hibernate.dialect.Dialect;
|
||||||
import org.hibernate.generator.Generator;
|
import org.hibernate.generator.Generator;
|
||||||
import org.hibernate.id.ForeignGenerator;
|
import org.hibernate.id.ForeignGenerator;
|
||||||
import org.hibernate.id.GUIDGenerator;
|
import org.hibernate.id.GUIDGenerator;
|
||||||
|
@ -113,4 +115,44 @@ public class GeneratorStrategies {
|
||||||
return clazz;
|
return clazz;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Class<? extends Generator> mapLegacyNamedGenerator(String strategy, Dialect dialect) {
|
||||||
|
if ( "native".equals(strategy) ) {
|
||||||
|
strategy = dialect.getNativeIdentifierGeneratorStrategy();
|
||||||
|
}
|
||||||
|
switch (strategy) {
|
||||||
|
case "assigned":
|
||||||
|
return org.hibernate.id.Assigned.class;
|
||||||
|
case "enhanced-sequence":
|
||||||
|
case "sequence":
|
||||||
|
return SequenceStyleGenerator.class;
|
||||||
|
case "enhanced-table":
|
||||||
|
case "table":
|
||||||
|
return org.hibernate.id.enhanced.TableGenerator.class;
|
||||||
|
case "identity":
|
||||||
|
return IdentityGenerator.class;
|
||||||
|
case "increment":
|
||||||
|
return IncrementGenerator.class;
|
||||||
|
case "foreign":
|
||||||
|
return ForeignGenerator.class;
|
||||||
|
case "uuid":
|
||||||
|
case "uuid.hex":
|
||||||
|
return UUIDHexGenerator.class;
|
||||||
|
case "uuid2":
|
||||||
|
return UUIDGenerator.class;
|
||||||
|
case "select":
|
||||||
|
return SelectGenerator.class;
|
||||||
|
case "guid":
|
||||||
|
return GUIDGenerator.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Class<? extends Generator> mapLegacyNamedGenerator(String strategy, MetadataBuildingContext buildingContext) {
|
||||||
|
return mapLegacyNamedGenerator( strategy, buildingContext.getMetadataCollector().getDatabase().getDialect() );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Class<? extends Generator> mapLegacyNamedGenerator(String strategy, SimpleValue idValue) {
|
||||||
|
return mapLegacyNamedGenerator( strategy, idValue.getMetadata().getDatabase().getDialect() );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -133,7 +133,8 @@ public class IdBagBinder extends BagBinder {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( isGlobalGeneratorNameGlobal( buildingContext ) ) {
|
if ( isGlobalGeneratorNameGlobal( buildingContext ) ) {
|
||||||
SecondPass secondPass = new IdGeneratorResolverSecondPass(
|
SecondPass secondPass = new IdBagIdGeneratorResolverSecondPass(
|
||||||
|
(IdentifierBag) collection,
|
||||||
id,
|
id,
|
||||||
property,
|
property,
|
||||||
generatorType,
|
generatorType,
|
||||||
|
|
|
@ -0,0 +1,303 @@
|
||||||
|
/*
|
||||||
|
* 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.boot.model.internal;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.hibernate.MappingException;
|
||||||
|
import org.hibernate.boot.model.IdentifierGeneratorDefinition;
|
||||||
|
import org.hibernate.boot.models.JpaAnnotations;
|
||||||
|
import org.hibernate.boot.models.annotations.internal.SequenceGeneratorJpaAnnotation;
|
||||||
|
import org.hibernate.boot.models.annotations.internal.TableGeneratorJpaAnnotation;
|
||||||
|
import org.hibernate.boot.models.spi.GlobalRegistrations;
|
||||||
|
import org.hibernate.boot.models.spi.SequenceGeneratorRegistration;
|
||||||
|
import org.hibernate.boot.models.spi.TableGeneratorRegistration;
|
||||||
|
import org.hibernate.boot.spi.MetadataBuildingContext;
|
||||||
|
import org.hibernate.generator.Generator;
|
||||||
|
import org.hibernate.id.PersistentIdentifierGenerator;
|
||||||
|
import org.hibernate.id.enhanced.SequenceStyleGenerator;
|
||||||
|
import org.hibernate.mapping.IdentifierBag;
|
||||||
|
import org.hibernate.mapping.PersistentClass;
|
||||||
|
import org.hibernate.mapping.SimpleValue;
|
||||||
|
import org.hibernate.models.spi.MemberDetails;
|
||||||
|
|
||||||
|
import jakarta.persistence.GeneratedValue;
|
||||||
|
import jakarta.persistence.SequenceGenerator;
|
||||||
|
import jakarta.persistence.TableGenerator;
|
||||||
|
|
||||||
|
import static org.hibernate.boot.model.internal.GeneratorAnnotationHelper.applyBaselineConfiguration;
|
||||||
|
import static org.hibernate.boot.model.internal.GeneratorBinder.createGeneratorFrom;
|
||||||
|
import static org.hibernate.boot.model.internal.GeneratorBinder.makeIdGenerator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IdGeneratorResolver for handling generators assigned to id-bag mappings
|
||||||
|
*
|
||||||
|
* @author Andrea Boriero
|
||||||
|
*/
|
||||||
|
public class IdBagIdGeneratorResolverSecondPass implements IdGeneratorResolver {
|
||||||
|
private final PersistentClass entityMapping;
|
||||||
|
private final SimpleValue idValue;
|
||||||
|
private final MemberDetails idAttributeMember;
|
||||||
|
private final String generatorType;
|
||||||
|
private final String generatorName;
|
||||||
|
private final MetadataBuildingContext buildingContext;
|
||||||
|
private final Map<String,String> configuration;
|
||||||
|
|
||||||
|
public IdBagIdGeneratorResolverSecondPass(
|
||||||
|
IdentifierBag idBagMapping,
|
||||||
|
SimpleValue idValue,
|
||||||
|
MemberDetails idAttributeMember,
|
||||||
|
String generatorType,
|
||||||
|
String generatorName,
|
||||||
|
MetadataBuildingContext buildingContext) {
|
||||||
|
this.entityMapping = null;
|
||||||
|
this.idValue = idValue;
|
||||||
|
this.idAttributeMember = idAttributeMember;
|
||||||
|
this.generatorType = generatorType;
|
||||||
|
this.generatorName = generatorName;
|
||||||
|
this.buildingContext = buildingContext;
|
||||||
|
|
||||||
|
this.configuration = new HashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void doSecondPass(Map<String, PersistentClass> idGeneratorDefinitionMap) throws MappingException {
|
||||||
|
final GeneratedValue generatedValue = idAttributeMember.getDirectAnnotationUsage( GeneratedValue.class );
|
||||||
|
switch ( generatedValue.strategy() ) {
|
||||||
|
case UUID -> GeneratorAnnotationHelper.handleUuidStrategy( idValue, idAttributeMember, buildingContext );
|
||||||
|
case IDENTITY -> GeneratorAnnotationHelper.handleIdentityStrategy( idValue, idAttributeMember, buildingContext );
|
||||||
|
case SEQUENCE -> handleSequenceStrategy(
|
||||||
|
generatorName,
|
||||||
|
idValue,
|
||||||
|
idAttributeMember,
|
||||||
|
buildingContext
|
||||||
|
);
|
||||||
|
case TABLE -> handleTableStrategy(
|
||||||
|
generatorName,
|
||||||
|
entityMapping,
|
||||||
|
idValue,
|
||||||
|
idAttributeMember,
|
||||||
|
generatedValue,
|
||||||
|
buildingContext
|
||||||
|
);
|
||||||
|
case AUTO -> handleAutoStrategy(
|
||||||
|
generatorName,
|
||||||
|
entityMapping,
|
||||||
|
idValue,
|
||||||
|
idAttributeMember,
|
||||||
|
generatedValue,
|
||||||
|
buildingContext
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleTableStrategy(
|
||||||
|
String generatorName,
|
||||||
|
PersistentClass entityMapping,
|
||||||
|
SimpleValue idValue,
|
||||||
|
MemberDetails idAttributeMember,
|
||||||
|
GeneratedValue generatedValue,
|
||||||
|
MetadataBuildingContext buildingContext) {
|
||||||
|
final GlobalRegistrations globalRegistrations = buildingContext.getMetadataCollector().getGlobalRegistrations();
|
||||||
|
final TableGeneratorRegistration globalTableGenerator = globalRegistrations.getTableGeneratorRegistrations().get( generatorName );
|
||||||
|
if ( globalTableGenerator != null ) {
|
||||||
|
handleTableGenerator(
|
||||||
|
generatorName,
|
||||||
|
globalTableGenerator.configuration(),
|
||||||
|
configuration,
|
||||||
|
idValue,
|
||||||
|
idAttributeMember,
|
||||||
|
buildingContext
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final TableGenerator localizedTableMatch = GeneratorAnnotationHelper.findLocalizedMatch(
|
||||||
|
JpaAnnotations.TABLE_GENERATOR,
|
||||||
|
idAttributeMember,
|
||||||
|
TableGenerator::name,
|
||||||
|
generatorName,
|
||||||
|
buildingContext
|
||||||
|
);
|
||||||
|
if ( localizedTableMatch != null ) {
|
||||||
|
handleTableGenerator( generatorName, localizedTableMatch, configuration, idValue, idAttributeMember, buildingContext );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GeneratorAnnotationHelper.handleTableGenerator(
|
||||||
|
generatorName,
|
||||||
|
new TableGeneratorJpaAnnotation( buildingContext.getMetadataCollector().getSourceModelBuildingContext() ),
|
||||||
|
entityMapping,
|
||||||
|
idValue,
|
||||||
|
idAttributeMember,
|
||||||
|
buildingContext
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleSequenceStrategy(
|
||||||
|
String generatorName,
|
||||||
|
SimpleValue idValue,
|
||||||
|
MemberDetails idAttributeMember,
|
||||||
|
MetadataBuildingContext buildingContext) {
|
||||||
|
final GlobalRegistrations globalRegistrations = buildingContext.getMetadataCollector().getGlobalRegistrations();
|
||||||
|
|
||||||
|
final SequenceGeneratorRegistration globalSequenceGenerator = globalRegistrations.getSequenceGeneratorRegistrations().get( generatorName );
|
||||||
|
if ( globalSequenceGenerator != null ) {
|
||||||
|
handleSequenceGenerator(
|
||||||
|
generatorName,
|
||||||
|
globalSequenceGenerator.configuration(),
|
||||||
|
configuration,
|
||||||
|
idValue,
|
||||||
|
idAttributeMember,
|
||||||
|
buildingContext
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final SequenceGenerator localizedSequencedMatch = GeneratorAnnotationHelper.findLocalizedMatch(
|
||||||
|
JpaAnnotations.SEQUENCE_GENERATOR,
|
||||||
|
idAttributeMember,
|
||||||
|
SequenceGenerator::name,
|
||||||
|
generatorName,
|
||||||
|
buildingContext
|
||||||
|
);
|
||||||
|
if ( localizedSequencedMatch != null ) {
|
||||||
|
handleSequenceGenerator( generatorName, localizedSequencedMatch, configuration, idValue, idAttributeMember, buildingContext );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
handleSequenceGenerator(
|
||||||
|
generatorName,
|
||||||
|
new SequenceGeneratorJpaAnnotation( buildingContext.getMetadataCollector().getSourceModelBuildingContext() ),
|
||||||
|
configuration,
|
||||||
|
idValue,
|
||||||
|
idAttributeMember,
|
||||||
|
buildingContext
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleAutoStrategy(
|
||||||
|
String generatorName,
|
||||||
|
PersistentClass entityMapping,
|
||||||
|
SimpleValue idValue,
|
||||||
|
MemberDetails idAttributeMember,
|
||||||
|
GeneratedValue generatedValue,
|
||||||
|
MetadataBuildingContext buildingContext) {
|
||||||
|
final GlobalRegistrations globalRegistrations = buildingContext.getMetadataCollector().getGlobalRegistrations();
|
||||||
|
|
||||||
|
final SequenceGeneratorRegistration globalSequenceGenerator = globalRegistrations.getSequenceGeneratorRegistrations().get( generatorName );
|
||||||
|
if ( globalSequenceGenerator != null ) {
|
||||||
|
handleSequenceGenerator(
|
||||||
|
generatorName,
|
||||||
|
globalSequenceGenerator.configuration(),
|
||||||
|
configuration,
|
||||||
|
idValue,
|
||||||
|
idAttributeMember,
|
||||||
|
buildingContext
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final TableGeneratorRegistration globalTableGenerator = globalRegistrations.getTableGeneratorRegistrations().get( generatorName );
|
||||||
|
if ( globalTableGenerator != null ) {
|
||||||
|
handleTableGenerator(
|
||||||
|
generatorName,
|
||||||
|
globalTableGenerator.configuration(),
|
||||||
|
configuration,
|
||||||
|
idValue,
|
||||||
|
idAttributeMember,
|
||||||
|
buildingContext
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
final Class<? extends Generator> legacyNamedGenerator = GeneratorStrategies.mapLegacyNamedGenerator( generatorName, idValue );
|
||||||
|
if ( legacyNamedGenerator != null ) {
|
||||||
|
//generator settings
|
||||||
|
if ( idValue.getColumnSpan() == 1 ) {
|
||||||
|
configuration.put( PersistentIdentifierGenerator.PK, idValue.getColumns().get(0).getName() );
|
||||||
|
}
|
||||||
|
createGeneratorFrom(
|
||||||
|
new IdentifierGeneratorDefinition( generatorName, legacyNamedGenerator.getName(), configuration ),
|
||||||
|
idAttributeMember,
|
||||||
|
idValue,
|
||||||
|
(Map) configuration,
|
||||||
|
buildingContext
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
final SequenceGenerator localizedSequencedMatch = GeneratorAnnotationHelper.findLocalizedMatch(
|
||||||
|
JpaAnnotations.SEQUENCE_GENERATOR,
|
||||||
|
idAttributeMember,
|
||||||
|
SequenceGenerator::name,
|
||||||
|
generatorName,
|
||||||
|
buildingContext
|
||||||
|
);
|
||||||
|
if ( localizedSequencedMatch != null ) {
|
||||||
|
handleSequenceGenerator( generatorName, localizedSequencedMatch, configuration, idValue, idAttributeMember, buildingContext );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final TableGenerator localizedTableMatch = GeneratorAnnotationHelper.findLocalizedMatch(
|
||||||
|
JpaAnnotations.TABLE_GENERATOR,
|
||||||
|
idAttributeMember,
|
||||||
|
TableGenerator::name,
|
||||||
|
generatorName,
|
||||||
|
buildingContext
|
||||||
|
);
|
||||||
|
if ( localizedTableMatch != null ) {
|
||||||
|
handleTableGenerator( generatorName, localizedTableMatch, configuration, idValue, idAttributeMember, buildingContext );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
makeIdGenerator( idValue, idAttributeMember, generatorType, generatorName, buildingContext, null );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void handleSequenceGenerator(
|
||||||
|
String generatorName,
|
||||||
|
SequenceGenerator generatorConfig,
|
||||||
|
Map<String,String> configuration,
|
||||||
|
SimpleValue idValue,
|
||||||
|
MemberDetails idMember,
|
||||||
|
MetadataBuildingContext context) {
|
||||||
|
applyBaselineConfiguration( generatorConfig, idValue, null, context, configuration::put );
|
||||||
|
SequenceStyleGenerator.applyConfiguration( generatorConfig, idValue, configuration::put );
|
||||||
|
|
||||||
|
createGeneratorFrom(
|
||||||
|
new IdentifierGeneratorDefinition( generatorName, SequenceStyleGenerator.class.getName(), configuration ),
|
||||||
|
idMember,
|
||||||
|
idValue,
|
||||||
|
(Map) configuration,
|
||||||
|
context
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void handleTableGenerator(
|
||||||
|
String generatorName,
|
||||||
|
TableGenerator generatorConfig,
|
||||||
|
Map<String,String> configuration,
|
||||||
|
SimpleValue idValue,
|
||||||
|
MemberDetails idMember,
|
||||||
|
MetadataBuildingContext context) {
|
||||||
|
GeneratorAnnotationHelper.applyBaselineConfiguration( generatorConfig, idValue, null, context, configuration::put );
|
||||||
|
org.hibernate.id.enhanced.TableGenerator.applyConfiguration( generatorConfig, idValue, configuration::put );
|
||||||
|
|
||||||
|
createGeneratorFrom(
|
||||||
|
new IdentifierGeneratorDefinition( generatorName, org.hibernate.id.enhanced.TableGenerator.class.getName(), configuration ),
|
||||||
|
idMember,
|
||||||
|
idValue,
|
||||||
|
(Map) configuration,
|
||||||
|
context
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
/*
|
||||||
|
* 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.boot.model.internal;
|
||||||
|
|
||||||
|
import org.hibernate.boot.spi.SecondPass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marker interface for second passes which bind id generators
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public interface IdGeneratorResolver extends SecondPass {
|
||||||
|
}
|
|
@ -6,68 +6,570 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.boot.model.internal;
|
package org.hibernate.boot.model.internal;
|
||||||
|
|
||||||
|
import java.lang.annotation.Annotation;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
|
import org.hibernate.annotations.GenericGenerator;
|
||||||
|
import org.hibernate.annotations.IdGeneratorType;
|
||||||
|
import org.hibernate.boot.model.IdentifierGeneratorDefinition;
|
||||||
|
import org.hibernate.boot.model.relational.ExportableProducer;
|
||||||
|
import org.hibernate.boot.models.HibernateAnnotations;
|
||||||
|
import org.hibernate.boot.models.JpaAnnotations;
|
||||||
|
import org.hibernate.boot.models.spi.GenericGeneratorRegistration;
|
||||||
|
import org.hibernate.boot.models.spi.SequenceGeneratorRegistration;
|
||||||
|
import org.hibernate.boot.models.spi.TableGeneratorRegistration;
|
||||||
|
import org.hibernate.boot.registry.StandardServiceRegistry;
|
||||||
import org.hibernate.boot.spi.MetadataBuildingContext;
|
import org.hibernate.boot.spi.MetadataBuildingContext;
|
||||||
import org.hibernate.boot.spi.SecondPass;
|
import org.hibernate.cfg.AvailableSettings;
|
||||||
|
import org.hibernate.engine.config.spi.ConfigurationService;
|
||||||
|
import org.hibernate.engine.config.spi.StandardConverters;
|
||||||
|
import org.hibernate.generator.Generator;
|
||||||
|
import org.hibernate.id.IdentityGenerator;
|
||||||
|
import org.hibernate.id.OptimizableGenerator;
|
||||||
|
import org.hibernate.id.enhanced.LegacyNamingStrategy;
|
||||||
|
import org.hibernate.id.enhanced.SequenceStyleGenerator;
|
||||||
|
import org.hibernate.id.enhanced.SingleNamingStrategy;
|
||||||
|
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||||
import org.hibernate.mapping.PersistentClass;
|
import org.hibernate.mapping.PersistentClass;
|
||||||
import org.hibernate.mapping.SimpleValue;
|
import org.hibernate.mapping.SimpleValue;
|
||||||
import org.hibernate.models.spi.MemberDetails;
|
import org.hibernate.models.spi.MemberDetails;
|
||||||
|
import org.hibernate.resource.beans.container.spi.BeanContainer;
|
||||||
|
|
||||||
import static org.hibernate.boot.model.internal.GeneratorBinder.makeIdGenerator;
|
import jakarta.persistence.GeneratedValue;
|
||||||
|
import jakarta.persistence.SequenceGenerator;
|
||||||
|
import jakarta.persistence.TableGenerator;
|
||||||
|
|
||||||
|
import static org.hibernate.boot.model.internal.GeneratorBinder.callConfigure;
|
||||||
|
import static org.hibernate.boot.model.internal.GeneratorStrategies.mapLegacyNamedGenerator;
|
||||||
|
import static org.hibernate.id.IdentifierGenerator.GENERATOR_NAME;
|
||||||
|
import static org.hibernate.id.OptimizableGenerator.INCREMENT_PARAM;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Andrea Boriero
|
* SecondPass implementing delayed resolution of id-generators associated with an entity.
|
||||||
|
*
|
||||||
|
* @see StrictIdGeneratorResolverSecondPass
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class IdGeneratorResolverSecondPass implements SecondPass {
|
public class IdGeneratorResolverSecondPass implements IdGeneratorResolver {
|
||||||
private final SimpleValue id;
|
private final PersistentClass entityMapping;
|
||||||
private final MemberDetails idAttributeMember;
|
private final SimpleValue idValue;
|
||||||
private final String generatorType;
|
private final MemberDetails idMember;
|
||||||
private final String generatorName;
|
private final GeneratedValue generatedValue;
|
||||||
private final MetadataBuildingContext buildingContext;
|
private final MetadataBuildingContext buildingContext;
|
||||||
// private IdentifierGeneratorDefinition localIdentifierGeneratorDefinition;
|
|
||||||
|
|
||||||
public IdGeneratorResolverSecondPass(
|
public IdGeneratorResolverSecondPass(
|
||||||
SimpleValue id,
|
PersistentClass entityMapping,
|
||||||
MemberDetails idAttributeMember,
|
SimpleValue idValue,
|
||||||
String generatorType,
|
MemberDetails idMember,
|
||||||
String generatorName,
|
GeneratedValue generatedValue,
|
||||||
MetadataBuildingContext buildingContext) {
|
MetadataBuildingContext buildingContext) {
|
||||||
this.id = id;
|
this.entityMapping = entityMapping;
|
||||||
this.idAttributeMember = idAttributeMember;
|
this.idValue = idValue;
|
||||||
this.generatorType = generatorType;
|
this.idMember = idMember;
|
||||||
this.generatorName = generatorName;
|
this.generatedValue = generatedValue;
|
||||||
this.buildingContext = buildingContext;
|
this.buildingContext = buildingContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
// public IdGeneratorResolverSecondPass(
|
|
||||||
// SimpleValue id,
|
|
||||||
// MemberDetails idAttributeMember,
|
|
||||||
// String generatorType,
|
|
||||||
// String generatorName,
|
|
||||||
// MetadataBuildingContext buildingContext,
|
|
||||||
// IdentifierGeneratorDefinition localIdentifierGeneratorDefinition) {
|
|
||||||
// this( id, idAttributeMember, generatorType, generatorName, buildingContext );
|
|
||||||
// this.localIdentifierGeneratorDefinition = localIdentifierGeneratorDefinition;
|
|
||||||
// }
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doSecondPass(Map<String, PersistentClass> idGeneratorDefinitionMap) throws MappingException {
|
public void doSecondPass(Map<String, PersistentClass> persistentClasses) throws MappingException {
|
||||||
// makeIdGenerator( id, idAttributeMember, generatorType, generatorName, buildingContext, localIdentifierGeneratorDefinition );
|
switch ( generatedValue.strategy() ) {
|
||||||
makeIdGenerator( id, idAttributeMember, generatorType, generatorName, buildingContext, null );
|
case UUID -> GeneratorAnnotationHelper.handleUuidStrategy( idValue, idMember, buildingContext );
|
||||||
|
case IDENTITY -> GeneratorAnnotationHelper.handleIdentityStrategy( idValue, idMember, buildingContext );
|
||||||
|
case SEQUENCE -> handleSequenceStrategy();
|
||||||
|
case TABLE -> handleTableStrategy();
|
||||||
|
case AUTO -> handleAutoStrategy();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// public static void makeIdGenerator(
|
private void handleSequenceStrategy() {
|
||||||
// SimpleValue id,
|
if ( generatedValue.generator().isEmpty() ) {
|
||||||
// MemberDetails idAttributeMember,
|
handleUnnamedSequenceGenerator();
|
||||||
// String generatorType,
|
}
|
||||||
// String generatorName,
|
else {
|
||||||
// MetadataBuildingContext buildingContext,
|
handleNamedSequenceGenerator();
|
||||||
// IdentifierGeneratorDefinition foreignKGeneratorDefinition) {
|
}
|
||||||
// makeIdGenerator( id, idAttributeMember, generatorType, generatorName, buildingContext,
|
}
|
||||||
// foreignKGeneratorDefinition != null
|
|
||||||
// ? Map.of( foreignKGeneratorDefinition.getName(), foreignKGeneratorDefinition )
|
private void handleUnnamedSequenceGenerator() {
|
||||||
// : null );
|
// todo (7.0) : null or entityMapping.getJpaEntityName() for "name from GeneratedValue"?
|
||||||
// }
|
|
||||||
|
final SequenceGenerator localizedMatch = GeneratorAnnotationHelper.findLocalizedMatch(
|
||||||
|
JpaAnnotations.SEQUENCE_GENERATOR,
|
||||||
|
idMember,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
buildingContext
|
||||||
|
);
|
||||||
|
if ( localizedMatch != null ) {
|
||||||
|
handleSequenceGenerator( null, localizedMatch );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
handleSequenceGenerator( null, null );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleNamedSequenceGenerator() {
|
||||||
|
final SequenceGenerator localizedMatch = GeneratorAnnotationHelper.findLocalizedMatch(
|
||||||
|
JpaAnnotations.SEQUENCE_GENERATOR,
|
||||||
|
idMember,
|
||||||
|
SequenceGenerator::name,
|
||||||
|
generatedValue.generator(),
|
||||||
|
buildingContext
|
||||||
|
);
|
||||||
|
if ( localizedMatch != null ) {
|
||||||
|
handleSequenceGenerator( generatedValue.generator(), localizedMatch );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// look for the matching global registration, if one.
|
||||||
|
final SequenceGeneratorRegistration globalMatch = buildingContext.getMetadataCollector()
|
||||||
|
.getGlobalRegistrations()
|
||||||
|
.getSequenceGeneratorRegistrations()
|
||||||
|
.get( generatedValue.generator() );
|
||||||
|
if ( globalMatch != null ) {
|
||||||
|
handleSequenceGenerator( generatedValue.generator(), globalMatch.configuration() );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
validateSequenceGeneration();
|
||||||
|
|
||||||
|
handleSequenceGenerator( generatedValue.generator(), null );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateSequenceGeneration() {
|
||||||
|
// basically, make sure there is neither a TableGenerator nor GenericGenerator with this name
|
||||||
|
|
||||||
|
final TableGeneratorRegistration globalTableMatch = buildingContext.getMetadataCollector()
|
||||||
|
.getGlobalRegistrations()
|
||||||
|
.getTableGeneratorRegistrations()
|
||||||
|
.get( generatedValue.generator() );
|
||||||
|
if ( globalTableMatch != null ) {
|
||||||
|
throw new MappingException(
|
||||||
|
String.format(
|
||||||
|
Locale.ROOT,
|
||||||
|
"@GeneratedValue for %s (%s) specified SEQUENCE generation, but referred to a @TableGenerator",
|
||||||
|
entityMapping.getEntityName(),
|
||||||
|
generatedValue.generator()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
final GenericGeneratorRegistration globalGenericMatch = buildingContext.getMetadataCollector()
|
||||||
|
.getGlobalRegistrations()
|
||||||
|
.getGenericGeneratorRegistrations()
|
||||||
|
.get( generatedValue.generator() );
|
||||||
|
if ( globalGenericMatch != null ) {
|
||||||
|
throw new MappingException(
|
||||||
|
String.format(
|
||||||
|
Locale.ROOT,
|
||||||
|
"@GeneratedValue for %s (%s) specified SEQUENCE generation, but referred to a @GenericGenerator",
|
||||||
|
entityMapping.getEntityName(),
|
||||||
|
generatedValue.generator()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleTableStrategy() {
|
||||||
|
if ( generatedValue.generator().isEmpty() ) {
|
||||||
|
handleUnnamedTableGenerator();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
handleNamedTableGenerator();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleUnnamedTableGenerator() {
|
||||||
|
// todo (7.0) : null or entityMapping.getJpaEntityName() for "name from GeneratedValue"?
|
||||||
|
|
||||||
|
final TableGenerator localizedMatch = GeneratorAnnotationHelper.findLocalizedMatch(
|
||||||
|
JpaAnnotations.TABLE_GENERATOR,
|
||||||
|
idMember,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
buildingContext
|
||||||
|
);
|
||||||
|
if ( localizedMatch != null ) {
|
||||||
|
handleTableGenerator( null, localizedMatch );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
handleTableGenerator( null, null );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleNamedTableGenerator() {
|
||||||
|
final TableGenerator localizedTableMatch = GeneratorAnnotationHelper.findLocalizedMatch(
|
||||||
|
JpaAnnotations.TABLE_GENERATOR,
|
||||||
|
idMember,
|
||||||
|
TableGenerator::name,
|
||||||
|
generatedValue.generator(),
|
||||||
|
buildingContext
|
||||||
|
);
|
||||||
|
if ( localizedTableMatch != null ) {
|
||||||
|
handleTableGenerator( generatedValue.generator(), localizedTableMatch );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// look for the matching global registration, if one.
|
||||||
|
final TableGeneratorRegistration globalMatch = buildingContext.getMetadataCollector()
|
||||||
|
.getGlobalRegistrations()
|
||||||
|
.getTableGeneratorRegistrations()
|
||||||
|
.get( generatedValue.generator() );
|
||||||
|
if ( globalMatch != null ) {
|
||||||
|
handleTableGenerator( generatedValue.generator(), globalMatch.configuration() );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
validateTableGeneration();
|
||||||
|
|
||||||
|
handleTableGenerator( generatedValue.generator(), null );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateTableGeneration() {
|
||||||
|
// basically, make sure there is neither a SequenceGenerator nor a GenericGenerator with this name
|
||||||
|
|
||||||
|
final SequenceGeneratorRegistration globalSequenceMatch = buildingContext.getMetadataCollector()
|
||||||
|
.getGlobalRegistrations()
|
||||||
|
.getSequenceGeneratorRegistrations()
|
||||||
|
.get( generatedValue.generator() );
|
||||||
|
if ( globalSequenceMatch != null ) {
|
||||||
|
throw new MappingException(
|
||||||
|
String.format(
|
||||||
|
Locale.ROOT,
|
||||||
|
"@GeneratedValue for %s (%s) specified TABLE generation, but referred to a @SequenceGenerator",
|
||||||
|
entityMapping.getEntityName(),
|
||||||
|
generatedValue.generator()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
final GenericGeneratorRegistration globalGenericMatch = buildingContext.getMetadataCollector()
|
||||||
|
.getGlobalRegistrations()
|
||||||
|
.getGenericGeneratorRegistrations()
|
||||||
|
.get( generatedValue.generator() );
|
||||||
|
if ( globalGenericMatch != null ) {
|
||||||
|
throw new MappingException(
|
||||||
|
String.format(
|
||||||
|
Locale.ROOT,
|
||||||
|
"@GeneratedValue for %s (%s) specified TABLE generation, but referred to a @GenericGenerator",
|
||||||
|
entityMapping.getEntityName(),
|
||||||
|
generatedValue.generator()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleAutoStrategy() {
|
||||||
|
if ( generatedValue.generator().isEmpty() ) {
|
||||||
|
handleUnnamedAutoGenerator();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
handleNamedAutoGenerator();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleUnnamedAutoGenerator() {
|
||||||
|
// todo (7.0) : null or entityMapping.getJpaEntityName() for "name from GeneratedValue"?
|
||||||
|
|
||||||
|
final SequenceGenerator localizedSequenceMatch = GeneratorAnnotationHelper.findLocalizedMatch(
|
||||||
|
JpaAnnotations.SEQUENCE_GENERATOR,
|
||||||
|
idMember,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
buildingContext
|
||||||
|
);
|
||||||
|
if ( localizedSequenceMatch != null ) {
|
||||||
|
handleSequenceGenerator( null, localizedSequenceMatch );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final TableGenerator localizedTableMatch = GeneratorAnnotationHelper.findLocalizedMatch(
|
||||||
|
JpaAnnotations.TABLE_GENERATOR,
|
||||||
|
idMember,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
buildingContext
|
||||||
|
);
|
||||||
|
if ( localizedTableMatch != null ) {
|
||||||
|
handleTableGenerator( null, localizedTableMatch );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final GenericGenerator localizedGenericMatch = GeneratorAnnotationHelper.findLocalizedMatch(
|
||||||
|
HibernateAnnotations.GENERIC_GENERATOR,
|
||||||
|
idMember,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
buildingContext
|
||||||
|
);
|
||||||
|
if ( localizedGenericMatch != null ) {
|
||||||
|
GeneratorAnnotationHelper.handleGenericGenerator(
|
||||||
|
entityMapping.getJpaEntityName(),
|
||||||
|
localizedGenericMatch,
|
||||||
|
entityMapping,
|
||||||
|
idValue,
|
||||||
|
idMember,
|
||||||
|
buildingContext
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( idMember.getType().isImplementor( UUID.class )
|
||||||
|
|| idMember.getType().isImplementor( String.class ) ) {
|
||||||
|
GeneratorAnnotationHelper.handleUuidStrategy( idValue, idMember, buildingContext );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
handleSequenceGenerator( null, null );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleNamedAutoGenerator() {
|
||||||
|
if ( handleAsLocalAutoGenerator() ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( handleAsNamedGlobalAutoGenerator() ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Class<? extends Generator> legacyNamedGenerator = mapLegacyNamedGenerator( generatedValue.generator(), buildingContext );
|
||||||
|
if ( legacyNamedGenerator != null ) {
|
||||||
|
//generator settings
|
||||||
|
GeneratorBinder.createGeneratorFrom(
|
||||||
|
new IdentifierGeneratorDefinition( generatedValue.generator(), legacyNamedGenerator.getName() ),
|
||||||
|
idMember,
|
||||||
|
idValue,
|
||||||
|
entityMapping,
|
||||||
|
buildingContext
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<? extends Annotation> metaAnnotated = idMember.getMetaAnnotated( IdGeneratorType.class, buildingContext.getMetadataCollector().getSourceModelBuildingContext() );
|
||||||
|
if ( CollectionHelper.size( metaAnnotated ) > 0 ) {
|
||||||
|
final Annotation generatorAnnotation = metaAnnotated.get( 0 );
|
||||||
|
final IdGeneratorType markerAnnotation = generatorAnnotation.annotationType().getAnnotation( IdGeneratorType.class );
|
||||||
|
idValue.setCustomIdGeneratorCreator( (creationContext) -> {
|
||||||
|
|
||||||
|
final BeanContainer beanContainer = GeneratorBinder.beanContainer( buildingContext );
|
||||||
|
final Generator identifierGenerator = GeneratorBinder.instantiateGenerator(
|
||||||
|
beanContainer,
|
||||||
|
markerAnnotation.value()
|
||||||
|
);
|
||||||
|
final Map<String,Object> configuration = new HashMap<>();
|
||||||
|
GeneratorParameters.collectParameters(
|
||||||
|
idValue,
|
||||||
|
buildingContext.getMetadataCollector().getDatabase().getDialect(),
|
||||||
|
entityMapping.getRootClass(),
|
||||||
|
configuration::put
|
||||||
|
);
|
||||||
|
callConfigure( creationContext, identifierGenerator, configuration, idValue );
|
||||||
|
return identifierGenerator;
|
||||||
|
} );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( idMember.getType().isImplementor( UUID.class )
|
||||||
|
|| idMember.getType().isImplementor( String.class ) ) {
|
||||||
|
GeneratorAnnotationHelper.handleUuidStrategy( idValue, idMember, buildingContext );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
handleSequenceGenerator( generatedValue.generator(), null );
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean handleAsLocalAutoGenerator() {
|
||||||
|
assert !generatedValue.generator().isEmpty();
|
||||||
|
|
||||||
|
final SequenceGenerator localizedSequenceMatch = GeneratorAnnotationHelper.findLocalizedMatch(
|
||||||
|
JpaAnnotations.SEQUENCE_GENERATOR,
|
||||||
|
idMember,
|
||||||
|
SequenceGenerator::name,
|
||||||
|
generatedValue.generator(),
|
||||||
|
buildingContext
|
||||||
|
);
|
||||||
|
if ( localizedSequenceMatch != null ) {
|
||||||
|
handleSequenceGenerator( generatedValue.generator(), localizedSequenceMatch );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
final TableGenerator localizedTableMatch = GeneratorAnnotationHelper.findLocalizedMatch(
|
||||||
|
JpaAnnotations.TABLE_GENERATOR,
|
||||||
|
idMember,
|
||||||
|
TableGenerator::name,
|
||||||
|
generatedValue.generator(),
|
||||||
|
buildingContext
|
||||||
|
);
|
||||||
|
if ( localizedTableMatch != null ) {
|
||||||
|
handleTableGenerator( generatedValue.generator(), localizedTableMatch );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
final GenericGenerator localizedGenericMatch = GeneratorAnnotationHelper.findLocalizedMatch(
|
||||||
|
HibernateAnnotations.GENERIC_GENERATOR,
|
||||||
|
idMember,
|
||||||
|
GenericGenerator::name,
|
||||||
|
generatedValue.generator(),
|
||||||
|
buildingContext
|
||||||
|
);
|
||||||
|
if ( localizedGenericMatch != null ) {
|
||||||
|
GeneratorAnnotationHelper.handleGenericGenerator(
|
||||||
|
generatedValue.generator(),
|
||||||
|
localizedGenericMatch,
|
||||||
|
entityMapping,
|
||||||
|
idValue,
|
||||||
|
idMember,
|
||||||
|
buildingContext
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean handleAsNamedGlobalAutoGenerator() {
|
||||||
|
final SequenceGeneratorRegistration globalSequenceMatch = buildingContext.getMetadataCollector()
|
||||||
|
.getGlobalRegistrations()
|
||||||
|
.getSequenceGeneratorRegistrations()
|
||||||
|
.get( generatedValue.generator() );
|
||||||
|
if ( globalSequenceMatch != null ) {
|
||||||
|
handleSequenceGenerator( generatedValue.generator(), globalSequenceMatch.configuration() );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
final TableGeneratorRegistration globalTableMatch = buildingContext.getMetadataCollector()
|
||||||
|
.getGlobalRegistrations()
|
||||||
|
.getTableGeneratorRegistrations()
|
||||||
|
.get( generatedValue.generator() );
|
||||||
|
if ( globalTableMatch != null ) {
|
||||||
|
handleTableGenerator( generatedValue.generator(), globalTableMatch.configuration() );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
final GenericGeneratorRegistration globalGenericMatch = buildingContext.getMetadataCollector()
|
||||||
|
.getGlobalRegistrations()
|
||||||
|
.getGenericGeneratorRegistrations()
|
||||||
|
.get( generatedValue.generator() );
|
||||||
|
if ( globalGenericMatch != null ) {
|
||||||
|
GeneratorAnnotationHelper.handleGenericGenerator(
|
||||||
|
generatedValue.generator(),
|
||||||
|
globalGenericMatch.configuration(),
|
||||||
|
entityMapping,
|
||||||
|
idValue,
|
||||||
|
idMember,
|
||||||
|
buildingContext
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleSequenceGenerator(String nameFromGeneratedValue, SequenceGenerator generator) {
|
||||||
|
final Map<String, Object> configuration = extractConfiguration( nameFromGeneratedValue, generator );
|
||||||
|
createGeneratorFrom( SequenceStyleGenerator.class, configuration );
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String,Object> extractConfiguration(String nameFromGenerated, SequenceGenerator generator) {
|
||||||
|
final Map<String, Object> configuration = new HashMap<>();
|
||||||
|
if ( generator != null ) {
|
||||||
|
configuration.put( GENERATOR_NAME, generator.name() );
|
||||||
|
}
|
||||||
|
else if ( nameFromGenerated != null ) {
|
||||||
|
configuration.put( GENERATOR_NAME, nameFromGenerated );
|
||||||
|
}
|
||||||
|
|
||||||
|
applyCommonConfiguration( configuration, generator );
|
||||||
|
|
||||||
|
if ( generator != null ) {
|
||||||
|
SequenceStyleGenerator.applyConfiguration( generator, idValue, configuration::put );
|
||||||
|
}
|
||||||
|
|
||||||
|
return configuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void applyCommonConfiguration(Map<String, Object> configuration, Annotation generatorAnnotation) {
|
||||||
|
GeneratorParameters.collectParameters(
|
||||||
|
idValue,
|
||||||
|
buildingContext.getMetadataCollector().getDatabase().getDialect(),
|
||||||
|
entityMapping.getRootClass(),
|
||||||
|
configuration::put
|
||||||
|
);
|
||||||
|
|
||||||
|
// we need to better handle default allocation-size here...
|
||||||
|
configuration.put( INCREMENT_PARAM, fallbackAllocationSize( buildingContext, generatorAnnotation ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int fallbackAllocationSize(MetadataBuildingContext buildingContext, Annotation generatorAnnotation) {
|
||||||
|
if ( generatorAnnotation == null ) {
|
||||||
|
// Special case where we have no matching SequenceGenerator/TableGenerator annotation.
|
||||||
|
// Historically we interpreted such cases using a default of 1, but JPA says the default
|
||||||
|
// here should be 50. As a migration aid, under the assumption that one of the legacy
|
||||||
|
// naming-strategies are used in such cases, we revert to the old default; otherwise we
|
||||||
|
// use the compliant value.
|
||||||
|
final StandardServiceRegistry serviceRegistry = buildingContext.getBootstrapContext().getServiceRegistry();
|
||||||
|
final ConfigurationService configService = serviceRegistry.requireService( ConfigurationService.class );
|
||||||
|
final String idNamingStrategy = configService.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 ) ) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return OptimizableGenerator.DEFAULT_INCREMENT_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleTableGenerator(String nameFromGeneratedValue, TableGenerator generator) {
|
||||||
|
final Map<String, Object> configuration = extractConfiguration( nameFromGeneratedValue, generator );
|
||||||
|
createGeneratorFrom( org.hibernate.id.enhanced.TableGenerator.class, configuration );
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String,Object> extractConfiguration(String nameFromGenerated, TableGenerator generator) {
|
||||||
|
final Map<String, Object> configuration = new HashMap<>();
|
||||||
|
if ( generator != null ) {
|
||||||
|
configuration.put( GENERATOR_NAME, generator.name() );
|
||||||
|
}
|
||||||
|
else if ( nameFromGenerated != null ) {
|
||||||
|
configuration.put( GENERATOR_NAME, nameFromGenerated );
|
||||||
|
}
|
||||||
|
|
||||||
|
applyCommonConfiguration( configuration, generator );
|
||||||
|
|
||||||
|
if ( generator != null ) {
|
||||||
|
org.hibernate.id.enhanced.TableGenerator.applyConfiguration( generator, idValue, configuration::put );
|
||||||
|
}
|
||||||
|
|
||||||
|
return configuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createGeneratorFrom(
|
||||||
|
Class<? extends Generator> generatorClass,
|
||||||
|
Map<String, Object> configuration) {
|
||||||
|
final BeanContainer beanContainer = GeneratorBinder.beanContainer( buildingContext );
|
||||||
|
idValue.setCustomIdGeneratorCreator( (creationContext) -> {
|
||||||
|
final Generator identifierGenerator = GeneratorBinder.instantiateGenerator( beanContainer, generatorClass );
|
||||||
|
callConfigure( creationContext, identifierGenerator, configuration, idValue );
|
||||||
|
if ( identifierGenerator instanceof IdentityGenerator ) {
|
||||||
|
idValue.setColumnToIdentity();
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we get here we have either a sequence or table generator,
|
||||||
|
// both of which are ExportableProducers
|
||||||
|
( (ExportableProducer) identifierGenerator ).registerExportables( creationContext.getDatabase() );
|
||||||
|
|
||||||
|
return identifierGenerator;
|
||||||
|
} );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -683,7 +683,6 @@ public class PropertyBinder {
|
||||||
PropertyHolder propertyHolder,
|
PropertyHolder propertyHolder,
|
||||||
Nullability nullability,
|
Nullability nullability,
|
||||||
PropertyData inferredData,
|
PropertyData inferredData,
|
||||||
Map<String, IdentifierGeneratorDefinition> classGenerators,
|
|
||||||
EntityBinder entityBinder,
|
EntityBinder entityBinder,
|
||||||
boolean isIdentifierMapper,
|
boolean isIdentifierMapper,
|
||||||
boolean isComponentEmbedded,
|
boolean isComponentEmbedded,
|
||||||
|
@ -721,7 +720,6 @@ public class PropertyBinder {
|
||||||
propertyHolder,
|
propertyHolder,
|
||||||
nullability,
|
nullability,
|
||||||
inferredData,
|
inferredData,
|
||||||
classGenerators,
|
|
||||||
entityBinder,
|
entityBinder,
|
||||||
isIdentifierMapper,
|
isIdentifierMapper,
|
||||||
isComponentEmbedded,
|
isComponentEmbedded,
|
||||||
|
@ -753,7 +751,6 @@ public class PropertyBinder {
|
||||||
PropertyHolder propertyHolder,
|
PropertyHolder propertyHolder,
|
||||||
Nullability nullability,
|
Nullability nullability,
|
||||||
PropertyData inferredData,
|
PropertyData inferredData,
|
||||||
Map<String, IdentifierGeneratorDefinition> classGenerators,
|
|
||||||
EntityBinder entityBinder,
|
EntityBinder entityBinder,
|
||||||
boolean isIdentifierMapper,
|
boolean isIdentifierMapper,
|
||||||
boolean isComponentEmbedded,
|
boolean isComponentEmbedded,
|
||||||
|
@ -797,7 +794,6 @@ public class PropertyBinder {
|
||||||
propertyHolder,
|
propertyHolder,
|
||||||
nullability,
|
nullability,
|
||||||
inferredData,
|
inferredData,
|
||||||
classGenerators,
|
|
||||||
entityBinder,
|
entityBinder,
|
||||||
isIdentifierMapper,
|
isIdentifierMapper,
|
||||||
isComponentEmbedded,
|
isComponentEmbedded,
|
||||||
|
@ -816,7 +812,6 @@ public class PropertyBinder {
|
||||||
PropertyHolder propertyHolder,
|
PropertyHolder propertyHolder,
|
||||||
Nullability nullability,
|
Nullability nullability,
|
||||||
PropertyData inferredData,
|
PropertyData inferredData,
|
||||||
Map<String, IdentifierGeneratorDefinition> classGenerators,
|
|
||||||
EntityBinder entityBinder,
|
EntityBinder entityBinder,
|
||||||
boolean isIdentifierMapper,
|
boolean isIdentifierMapper,
|
||||||
boolean isComponentEmbedded,
|
boolean isComponentEmbedded,
|
||||||
|
@ -879,7 +874,6 @@ public class PropertyBinder {
|
||||||
propertyHolder,
|
propertyHolder,
|
||||||
nullability,
|
nullability,
|
||||||
inferredData,
|
inferredData,
|
||||||
classGenerators,
|
|
||||||
entityBinder,
|
entityBinder,
|
||||||
isIdentifierMapper,
|
isIdentifierMapper,
|
||||||
context,
|
context,
|
||||||
|
@ -895,7 +889,6 @@ public class PropertyBinder {
|
||||||
propertyHolder,
|
propertyHolder,
|
||||||
nullability,
|
nullability,
|
||||||
inferredData,
|
inferredData,
|
||||||
classGenerators,
|
|
||||||
entityBinder,
|
entityBinder,
|
||||||
isIdentifierMapper,
|
isIdentifierMapper,
|
||||||
isComponentEmbedded,
|
isComponentEmbedded,
|
||||||
|
@ -996,7 +989,6 @@ public class PropertyBinder {
|
||||||
PropertyHolder propertyHolder,
|
PropertyHolder propertyHolder,
|
||||||
Nullability nullability,
|
Nullability nullability,
|
||||||
PropertyData inferredData,
|
PropertyData inferredData,
|
||||||
Map<String, IdentifierGeneratorDefinition> classGenerators,
|
|
||||||
EntityBinder entityBinder,
|
EntityBinder entityBinder,
|
||||||
boolean isIdentifierMapper,
|
boolean isIdentifierMapper,
|
||||||
boolean isComponentEmbedded,
|
boolean isComponentEmbedded,
|
||||||
|
@ -1145,7 +1137,6 @@ public class PropertyBinder {
|
||||||
propertyHolder,
|
propertyHolder,
|
||||||
inferredData,
|
inferredData,
|
||||||
(SimpleValue) propertyBinder.getValue(),
|
(SimpleValue) propertyBinder.getValue(),
|
||||||
classGenerators,
|
|
||||||
context
|
context
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,365 @@
|
||||||
|
/*
|
||||||
|
* 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.boot.model.internal;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import org.hibernate.MappingException;
|
||||||
|
import org.hibernate.boot.model.IdentifierGeneratorDefinition;
|
||||||
|
import org.hibernate.boot.model.relational.Database;
|
||||||
|
import org.hibernate.boot.models.annotations.internal.SequenceGeneratorJpaAnnotation;
|
||||||
|
import org.hibernate.boot.models.annotations.internal.TableGeneratorJpaAnnotation;
|
||||||
|
import org.hibernate.boot.models.spi.GenericGeneratorRegistration;
|
||||||
|
import org.hibernate.boot.models.spi.SequenceGeneratorRegistration;
|
||||||
|
import org.hibernate.boot.models.spi.TableGeneratorRegistration;
|
||||||
|
import org.hibernate.boot.spi.MetadataBuildingContext;
|
||||||
|
import org.hibernate.dialect.Dialect;
|
||||||
|
import org.hibernate.generator.Generator;
|
||||||
|
import org.hibernate.id.enhanced.SequenceStyleGenerator;
|
||||||
|
import org.hibernate.mapping.Column;
|
||||||
|
import org.hibernate.mapping.PersistentClass;
|
||||||
|
import org.hibernate.mapping.SimpleValue;
|
||||||
|
import org.hibernate.models.spi.MemberDetails;
|
||||||
|
|
||||||
|
import jakarta.persistence.GeneratedValue;
|
||||||
|
import jakarta.persistence.SequenceGenerator;
|
||||||
|
|
||||||
|
import static org.hibernate.boot.model.internal.GeneratorAnnotationHelper.*;
|
||||||
|
import static org.hibernate.boot.model.internal.GeneratorAnnotationHelper.handleUuidStrategy;
|
||||||
|
import static org.hibernate.boot.model.internal.GeneratorParameters.identityTablesString;
|
||||||
|
import static org.hibernate.id.IdentifierGenerator.ENTITY_NAME;
|
||||||
|
import static org.hibernate.id.IdentifierGenerator.GENERATOR_NAME;
|
||||||
|
import static org.hibernate.id.IdentifierGenerator.JPA_ENTITY_NAME;
|
||||||
|
import static org.hibernate.id.OptimizableGenerator.IMPLICIT_NAME_BASE;
|
||||||
|
import static org.hibernate.id.PersistentIdentifierGenerator.PK;
|
||||||
|
import static org.hibernate.id.PersistentIdentifierGenerator.TABLE;
|
||||||
|
import static org.hibernate.id.PersistentIdentifierGenerator.TABLES;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SecondPass implementing delayed resolution of id-generators associated with an entity
|
||||||
|
* using strict JPA resolution - based mainly on global resolution of generator names,
|
||||||
|
* along with support for UUID and String member types with AUTO. We also account for
|
||||||
|
* legacy (un-configurable) named generators ({@code increment}, {@code uuid.hex}, etc.).
|
||||||
|
*
|
||||||
|
* @implNote For unnamed generators defined on the entity class or on the id member, this
|
||||||
|
* strategy will register a global registration using the entity's name and later look it
|
||||||
|
* up by that name. This more strictly follows the JPA specification where all generator
|
||||||
|
* names should be considered global and resolved globally.
|
||||||
|
*
|
||||||
|
* @see IdGeneratorResolverSecondPass
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class StrictIdGeneratorResolverSecondPass implements IdGeneratorResolver {
|
||||||
|
private final PersistentClass entityMapping;
|
||||||
|
private final SimpleValue idValue;
|
||||||
|
private final MemberDetails idMember;
|
||||||
|
|
||||||
|
private final MetadataBuildingContext buildingContext;
|
||||||
|
|
||||||
|
public StrictIdGeneratorResolverSecondPass(
|
||||||
|
PersistentClass entityMapping,
|
||||||
|
SimpleValue idValue,
|
||||||
|
MemberDetails idMember,
|
||||||
|
MetadataBuildingContext buildingContext) {
|
||||||
|
this.entityMapping = entityMapping;
|
||||||
|
this.idValue = idValue;
|
||||||
|
this.idMember = idMember;
|
||||||
|
this.buildingContext = buildingContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void doSecondPass(Map<String, PersistentClass> persistentClasses) throws MappingException {
|
||||||
|
final GeneratedValue generatedValue = idMember.getDirectAnnotationUsage( GeneratedValue.class );
|
||||||
|
switch ( generatedValue.strategy() ) {
|
||||||
|
case UUID -> handleUuidStrategy( idValue, idMember, buildingContext );
|
||||||
|
case IDENTITY -> handleIdentityStrategy( idValue, idMember, buildingContext );
|
||||||
|
case SEQUENCE -> handleSequenceStrategy( generatedValue );
|
||||||
|
case TABLE -> handleTableStrategy( generatedValue );
|
||||||
|
case AUTO -> handleAutoStrategy( generatedValue );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleSequenceStrategy(GeneratedValue generatedValue) {
|
||||||
|
if ( generatedValue.generator().isEmpty() ) {
|
||||||
|
handleUnnamedSequenceGenerator();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
handleNamedSequenceGenerator( generatedValue );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleUnnamedSequenceGenerator() {
|
||||||
|
// according to the spec, this should locate a generator with the same name as the entity-name
|
||||||
|
final SequenceGeneratorRegistration globalMatch = buildingContext.getMetadataCollector()
|
||||||
|
.getGlobalRegistrations()
|
||||||
|
.getSequenceGeneratorRegistrations()
|
||||||
|
.get( entityMapping.getJpaEntityName() );
|
||||||
|
if ( globalMatch != null ) {
|
||||||
|
handleSequenceGenerator(
|
||||||
|
entityMapping.getJpaEntityName(),
|
||||||
|
globalMatch.configuration(),
|
||||||
|
entityMapping,
|
||||||
|
idValue,
|
||||||
|
idMember,
|
||||||
|
buildingContext
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
handleSequenceGenerator(
|
||||||
|
entityMapping.getJpaEntityName(),
|
||||||
|
new SequenceGeneratorJpaAnnotation( buildingContext.getMetadataCollector().getSourceModelBuildingContext() ),
|
||||||
|
entityMapping,
|
||||||
|
idValue,
|
||||||
|
idMember,
|
||||||
|
buildingContext
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleNamedSequenceGenerator(GeneratedValue generatedValue) {
|
||||||
|
final SequenceGeneratorRegistration globalMatch = buildingContext.getMetadataCollector()
|
||||||
|
.getGlobalRegistrations()
|
||||||
|
.getSequenceGeneratorRegistrations()
|
||||||
|
.get( generatedValue.generator() );
|
||||||
|
if ( globalMatch != null ) {
|
||||||
|
handleSequenceGenerator(
|
||||||
|
generatedValue.generator(),
|
||||||
|
globalMatch.configuration(),
|
||||||
|
entityMapping,
|
||||||
|
idValue,
|
||||||
|
idMember,
|
||||||
|
buildingContext
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
handleSequenceGenerator(
|
||||||
|
generatedValue.generator(),
|
||||||
|
new SequenceGeneratorJpaAnnotation( generatedValue.generator(), buildingContext.getMetadataCollector().getSourceModelBuildingContext() ),
|
||||||
|
entityMapping,
|
||||||
|
idValue,
|
||||||
|
idMember,
|
||||||
|
buildingContext
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleTableStrategy(GeneratedValue generatedValue) {
|
||||||
|
if ( generatedValue.generator().isEmpty() ) {
|
||||||
|
handleUnnamedTableGenerator();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
handleNamedTableGenerator( generatedValue );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleUnnamedTableGenerator() {
|
||||||
|
final TableGeneratorRegistration globalMatch = buildingContext.getMetadataCollector()
|
||||||
|
.getGlobalRegistrations()
|
||||||
|
.getTableGeneratorRegistrations()
|
||||||
|
.get( entityMapping.getJpaEntityName() );
|
||||||
|
if ( globalMatch != null ) {
|
||||||
|
handleTableGenerator(
|
||||||
|
entityMapping.getJpaEntityName(),
|
||||||
|
globalMatch.configuration(),
|
||||||
|
entityMapping,
|
||||||
|
idValue,
|
||||||
|
idMember,
|
||||||
|
buildingContext
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
handleTableGenerator(
|
||||||
|
entityMapping.getJpaEntityName(),
|
||||||
|
new TableGeneratorJpaAnnotation( buildingContext.getMetadataCollector().getSourceModelBuildingContext() ),
|
||||||
|
entityMapping,
|
||||||
|
idValue,
|
||||||
|
idMember,
|
||||||
|
buildingContext
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleNamedTableGenerator(GeneratedValue generatedValue) {
|
||||||
|
final TableGeneratorRegistration globalMatch = buildingContext.getMetadataCollector()
|
||||||
|
.getGlobalRegistrations()
|
||||||
|
.getTableGeneratorRegistrations()
|
||||||
|
.get( generatedValue.generator() );
|
||||||
|
if ( globalMatch != null ) {
|
||||||
|
handleTableGenerator(
|
||||||
|
generatedValue.generator(),
|
||||||
|
globalMatch.configuration(),
|
||||||
|
entityMapping,
|
||||||
|
idValue,
|
||||||
|
idMember,
|
||||||
|
buildingContext
|
||||||
|
);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
handleTableGenerator(
|
||||||
|
generatedValue.generator(),
|
||||||
|
new TableGeneratorJpaAnnotation( generatedValue.generator(), buildingContext.getMetadataCollector().getSourceModelBuildingContext() ),
|
||||||
|
entityMapping,
|
||||||
|
idValue,
|
||||||
|
idMember,
|
||||||
|
buildingContext
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleAutoStrategy(GeneratedValue generatedValue) {
|
||||||
|
final String globalRegistrationName;
|
||||||
|
if ( generatedValue.generator().isEmpty() ) {
|
||||||
|
globalRegistrationName = entityMapping.getJpaEntityName();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
globalRegistrationName = generatedValue.generator();
|
||||||
|
}
|
||||||
|
|
||||||
|
final SequenceGeneratorRegistration globalSequenceMatch = buildingContext.getMetadataCollector()
|
||||||
|
.getGlobalRegistrations()
|
||||||
|
.getSequenceGeneratorRegistrations()
|
||||||
|
.get( globalRegistrationName );
|
||||||
|
if ( globalSequenceMatch != null ) {
|
||||||
|
handleSequenceGenerator(
|
||||||
|
globalRegistrationName,
|
||||||
|
globalSequenceMatch.configuration(),
|
||||||
|
entityMapping,
|
||||||
|
idValue,
|
||||||
|
idMember,
|
||||||
|
buildingContext
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final TableGeneratorRegistration globalTableMatch = buildingContext.getMetadataCollector()
|
||||||
|
.getGlobalRegistrations()
|
||||||
|
.getTableGeneratorRegistrations()
|
||||||
|
.get( globalRegistrationName );
|
||||||
|
if ( globalTableMatch != null ) {
|
||||||
|
handleTableGenerator(
|
||||||
|
globalRegistrationName,
|
||||||
|
globalTableMatch.configuration(),
|
||||||
|
entityMapping,
|
||||||
|
idValue,
|
||||||
|
idMember,
|
||||||
|
buildingContext
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final GenericGeneratorRegistration globalGenericMatch = buildingContext.getMetadataCollector()
|
||||||
|
.getGlobalRegistrations()
|
||||||
|
.getGenericGeneratorRegistrations()
|
||||||
|
.get( globalRegistrationName );
|
||||||
|
if ( globalGenericMatch != null ) {
|
||||||
|
handleGenericGenerator(
|
||||||
|
globalRegistrationName,
|
||||||
|
globalGenericMatch.configuration(),
|
||||||
|
entityMapping,
|
||||||
|
idValue,
|
||||||
|
idMember,
|
||||||
|
buildingContext
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implicit handling of UUID generation
|
||||||
|
if ( idMember.getType().isImplementor( UUID.class )
|
||||||
|
|| idMember.getType().isImplementor( String.class )) {
|
||||||
|
handleUuidStrategy( idValue, idMember, buildingContext );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Handle a few legacy Hibernate generators...
|
||||||
|
if ( !generatedValue.generator().isEmpty() ) {
|
||||||
|
final Class<? extends Generator> legacyNamedGenerator = GeneratorStrategies.mapLegacyNamedGenerator( generatedValue.generator(), idValue );
|
||||||
|
if ( legacyNamedGenerator != null ) {
|
||||||
|
final Map<String,String> configuration = buildLegacyGeneratorConfig();
|
||||||
|
//noinspection unchecked,rawtypes
|
||||||
|
GeneratorBinder.createGeneratorFrom(
|
||||||
|
new IdentifierGeneratorDefinition( generatedValue.generator(), legacyNamedGenerator.getName(), configuration ),
|
||||||
|
idMember,
|
||||||
|
idValue,
|
||||||
|
(Map) configuration,
|
||||||
|
buildingContext
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleSequenceGenerator(
|
||||||
|
globalRegistrationName,
|
||||||
|
new SequenceGeneratorJpaAnnotation( generatedValue.generator(), buildingContext.getMetadataCollector().getSourceModelBuildingContext() ),
|
||||||
|
entityMapping,
|
||||||
|
idValue,
|
||||||
|
idMember,
|
||||||
|
buildingContext
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private HashMap<String, String> buildLegacyGeneratorConfig() {
|
||||||
|
final Database database = buildingContext.getMetadataCollector().getDatabase();
|
||||||
|
final Dialect dialect = database.getDialect();
|
||||||
|
|
||||||
|
final HashMap<String, String> configuration = new HashMap<>();
|
||||||
|
|
||||||
|
final String tableName = idValue.getTable().getQuotedName( dialect );
|
||||||
|
configuration.put( TABLE, tableName );
|
||||||
|
|
||||||
|
final Column idColumn = (Column) idValue.getSelectables().get( 0);
|
||||||
|
final String idColumnName = idColumn.getQuotedName( dialect );
|
||||||
|
configuration.put( PK, idColumnName );
|
||||||
|
|
||||||
|
configuration.put( ENTITY_NAME, entityMapping.getEntityName() );
|
||||||
|
configuration.put( JPA_ENTITY_NAME, entityMapping.getJpaEntityName() );
|
||||||
|
|
||||||
|
// The table name is not really a good default for subselect entities,
|
||||||
|
// so use the JPA entity name which is short
|
||||||
|
configuration.put(
|
||||||
|
IMPLICIT_NAME_BASE,
|
||||||
|
idValue.getTable().isSubselect()
|
||||||
|
? entityMapping.getJpaEntityName()
|
||||||
|
: idValue.getTable().getName()
|
||||||
|
);
|
||||||
|
|
||||||
|
configuration.put( TABLES, identityTablesString( dialect, entityMapping.getRootClass() ) );
|
||||||
|
|
||||||
|
return configuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void handleSequenceGenerator(
|
||||||
|
String generatorName,
|
||||||
|
SequenceGenerator generatorConfig,
|
||||||
|
PersistentClass entityMapping,
|
||||||
|
SimpleValue idValue,
|
||||||
|
MemberDetails idMember,
|
||||||
|
MetadataBuildingContext context) {
|
||||||
|
//generator settings
|
||||||
|
final Map<String, String> configuration = new HashMap<>();
|
||||||
|
applyBaselineConfiguration( generatorConfig, idValue, entityMapping.getRootClass(), context, configuration::put );
|
||||||
|
if ( generatorConfig == null ) {
|
||||||
|
configuration.put( GENERATOR_NAME, generatorName );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
SequenceStyleGenerator.applyConfiguration( generatorConfig, idValue, configuration::put );
|
||||||
|
}
|
||||||
|
|
||||||
|
GeneratorBinder.createGeneratorFrom(
|
||||||
|
new IdentifierGeneratorDefinition( generatorName, SequenceStyleGenerator.class.getName(), configuration ),
|
||||||
|
idMember,
|
||||||
|
idValue,
|
||||||
|
entityMapping,
|
||||||
|
context
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -28,7 +28,18 @@ public class SequenceGeneratorJpaAnnotation implements SequenceGenerator {
|
||||||
* Used in creating dynamic annotation instances (e.g. from XML)
|
* Used in creating dynamic annotation instances (e.g. from XML)
|
||||||
*/
|
*/
|
||||||
public SequenceGeneratorJpaAnnotation(SourceModelBuildingContext modelContext) {
|
public SequenceGeneratorJpaAnnotation(SourceModelBuildingContext modelContext) {
|
||||||
this.name = "";
|
this( "", modelContext );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used in creating named, defaulted annotation instances. Generally this
|
||||||
|
* is a situation where we have:<ol>
|
||||||
|
* <li>{@linkplain GeneratedValue#strategy()} set to {@linkplain jakarta.persistence.GenerationType#SEQUENCE}</li>
|
||||||
|
* <li>{@linkplain GeneratedValue#generator()} set to a non-empty String, but with no matching {@linkplain SequenceGenerator}</li>
|
||||||
|
* </ol>
|
||||||
|
*/
|
||||||
|
public SequenceGeneratorJpaAnnotation(String name, SourceModelBuildingContext modelContext) {
|
||||||
|
this.name = name;
|
||||||
this.sequenceName = "";
|
this.sequenceName = "";
|
||||||
this.catalog = "";
|
this.catalog = "";
|
||||||
this.schema = "";
|
this.schema = "";
|
||||||
|
|
|
@ -43,7 +43,18 @@ public class TableGeneratorJpaAnnotation implements TableGenerator, UniqueConstr
|
||||||
* Used in creating dynamic annotation instances (e.g. from XML)
|
* Used in creating dynamic annotation instances (e.g. from XML)
|
||||||
*/
|
*/
|
||||||
public TableGeneratorJpaAnnotation(SourceModelBuildingContext modelContext) {
|
public TableGeneratorJpaAnnotation(SourceModelBuildingContext modelContext) {
|
||||||
this.name = "";
|
this( "", modelContext );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used in creating named, defaulted annotation instances. Generally this
|
||||||
|
* is a situation where we have:<ol>
|
||||||
|
* <li>{@linkplain GeneratedValue#strategy()} set to {@linkplain jakarta.persistence.GenerationType#TABLE}</li>
|
||||||
|
* <li>{@linkplain GeneratedValue#generator()} set to a non-empty String, but with no matching {@linkplain TableGenerator}</li>
|
||||||
|
* </ol>
|
||||||
|
*/
|
||||||
|
public TableGeneratorJpaAnnotation(String name, SourceModelBuildingContext modelContext) {
|
||||||
|
this.name = name;
|
||||||
this.table = "";
|
this.table = "";
|
||||||
this.catalog = "";
|
this.catalog = "";
|
||||||
this.schema = "";
|
this.schema = "";
|
||||||
|
|
|
@ -117,9 +117,7 @@ public class DomainModelCategorizationCollector {
|
||||||
getGlobalRegistrations().collectEmbeddableInstantiatorRegistrations( classDetails );
|
getGlobalRegistrations().collectEmbeddableInstantiatorRegistrations( classDetails );
|
||||||
getGlobalRegistrations().collectFilterDefinitions( classDetails );
|
getGlobalRegistrations().collectFilterDefinitions( classDetails );
|
||||||
|
|
||||||
if ( areIdGeneratorsGlobal ) {
|
|
||||||
getGlobalRegistrations().collectIdGenerators( classDetails );
|
getGlobalRegistrations().collectIdGenerators( classDetails );
|
||||||
}
|
|
||||||
|
|
||||||
getGlobalRegistrations().collectImportRename( classDetails );
|
getGlobalRegistrations().collectImportRename( classDetails );
|
||||||
|
|
||||||
|
|
|
@ -11,10 +11,12 @@ import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import org.hibernate.MappingException;
|
||||||
import org.hibernate.annotations.GenericGenerator;
|
import org.hibernate.annotations.GenericGenerator;
|
||||||
import org.hibernate.annotations.Imported;
|
import org.hibernate.annotations.Imported;
|
||||||
import org.hibernate.annotations.ParamDef;
|
import org.hibernate.annotations.ParamDef;
|
||||||
|
@ -56,6 +58,7 @@ import org.hibernate.boot.models.spi.ConverterRegistration;
|
||||||
import org.hibernate.boot.models.spi.EmbeddableInstantiatorRegistration;
|
import org.hibernate.boot.models.spi.EmbeddableInstantiatorRegistration;
|
||||||
import org.hibernate.boot.models.spi.FilterDefRegistration;
|
import org.hibernate.boot.models.spi.FilterDefRegistration;
|
||||||
import org.hibernate.boot.models.spi.GenericGeneratorRegistration;
|
import org.hibernate.boot.models.spi.GenericGeneratorRegistration;
|
||||||
|
import org.hibernate.boot.models.spi.GlobalRegistrar;
|
||||||
import org.hibernate.boot.models.spi.GlobalRegistrations;
|
import org.hibernate.boot.models.spi.GlobalRegistrations;
|
||||||
import org.hibernate.boot.models.spi.JavaTypeRegistration;
|
import org.hibernate.boot.models.spi.JavaTypeRegistration;
|
||||||
import org.hibernate.boot.models.spi.JdbcTypeRegistration;
|
import org.hibernate.boot.models.spi.JdbcTypeRegistration;
|
||||||
|
@ -81,12 +84,15 @@ import org.hibernate.metamodel.CollectionClassification;
|
||||||
import org.hibernate.metamodel.spi.EmbeddableInstantiator;
|
import org.hibernate.metamodel.spi.EmbeddableInstantiator;
|
||||||
import org.hibernate.models.spi.AnnotationTarget;
|
import org.hibernate.models.spi.AnnotationTarget;
|
||||||
import org.hibernate.models.spi.ClassDetails;
|
import org.hibernate.models.spi.ClassDetails;
|
||||||
|
import org.hibernate.models.spi.MemberDetails;
|
||||||
import org.hibernate.models.spi.SourceModelBuildingContext;
|
import org.hibernate.models.spi.SourceModelBuildingContext;
|
||||||
import org.hibernate.usertype.CompositeUserType;
|
import org.hibernate.usertype.CompositeUserType;
|
||||||
import org.hibernate.usertype.UserCollectionType;
|
import org.hibernate.usertype.UserCollectionType;
|
||||||
import org.hibernate.usertype.UserType;
|
import org.hibernate.usertype.UserType;
|
||||||
|
|
||||||
import jakarta.persistence.AttributeConverter;
|
import jakarta.persistence.AttributeConverter;
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.GenerationType;
|
||||||
import jakarta.persistence.QueryHint;
|
import jakarta.persistence.QueryHint;
|
||||||
import jakarta.persistence.SequenceGenerator;
|
import jakarta.persistence.SequenceGenerator;
|
||||||
import jakarta.persistence.TableGenerator;
|
import jakarta.persistence.TableGenerator;
|
||||||
|
@ -102,6 +108,7 @@ import static org.hibernate.boot.models.HibernateAnnotations.FILTER_DEF;
|
||||||
import static org.hibernate.boot.models.HibernateAnnotations.GENERIC_GENERATOR;
|
import static org.hibernate.boot.models.HibernateAnnotations.GENERIC_GENERATOR;
|
||||||
import static org.hibernate.boot.models.HibernateAnnotations.JAVA_TYPE_REGISTRATION;
|
import static org.hibernate.boot.models.HibernateAnnotations.JAVA_TYPE_REGISTRATION;
|
||||||
import static org.hibernate.boot.models.HibernateAnnotations.JDBC_TYPE_REGISTRATION;
|
import static org.hibernate.boot.models.HibernateAnnotations.JDBC_TYPE_REGISTRATION;
|
||||||
|
import static org.hibernate.boot.models.JpaAnnotations.ENTITY;
|
||||||
import static org.hibernate.boot.models.JpaAnnotations.NAMED_STORED_PROCEDURE_QUERY;
|
import static org.hibernate.boot.models.JpaAnnotations.NAMED_STORED_PROCEDURE_QUERY;
|
||||||
import static org.hibernate.boot.models.JpaAnnotations.SEQUENCE_GENERATOR;
|
import static org.hibernate.boot.models.JpaAnnotations.SEQUENCE_GENERATOR;
|
||||||
import static org.hibernate.boot.models.JpaAnnotations.TABLE_GENERATOR;
|
import static org.hibernate.boot.models.JpaAnnotations.TABLE_GENERATOR;
|
||||||
|
@ -113,7 +120,7 @@ import static org.hibernate.internal.util.collections.CollectionHelper.isEmpty;
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class GlobalRegistrationsImpl implements GlobalRegistrations {
|
public class GlobalRegistrationsImpl implements GlobalRegistrations, GlobalRegistrar {
|
||||||
private final SourceModelBuildingContext sourceModelContext;
|
private final SourceModelBuildingContext sourceModelContext;
|
||||||
private final BootstrapContext bootstrapContext;
|
private final BootstrapContext bootstrapContext;
|
||||||
|
|
||||||
|
@ -144,6 +151,12 @@ public class GlobalRegistrationsImpl implements GlobalRegistrations {
|
||||||
this.bootstrapContext = bootstrapContext;
|
this.bootstrapContext = bootstrapContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> T as(Class<T> type) {
|
||||||
|
//noinspection unchecked
|
||||||
|
return (T) this;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<JpaEventListener> getEntityListenerRegistrations() {
|
public List<JpaEventListener> getEntityListenerRegistrations() {
|
||||||
return jpaEventListeners == null ? emptyList() : jpaEventListeners;
|
return jpaEventListeners == null ? emptyList() : jpaEventListeners;
|
||||||
|
@ -691,15 +704,20 @@ public class GlobalRegistrationsImpl implements GlobalRegistrations {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void collectIdGenerators(ClassDetails classDetails) {
|
public void collectIdGenerators(ClassDetails classDetails) {
|
||||||
|
if ( !classDetails.getName().endsWith( ".package-info" )
|
||||||
|
&& !bootstrapContext.getJpaCompliance().isGlobalGeneratorScopeEnabled() ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
classDetails.forEachRepeatedAnnotationUsages(
|
classDetails.forEachRepeatedAnnotationUsages(
|
||||||
SEQUENCE_GENERATOR,
|
SEQUENCE_GENERATOR,
|
||||||
sourceModelContext,
|
sourceModelContext,
|
||||||
this::collectSequenceGenerator
|
(sequenceGenerator) -> collectSequenceGenerator( classDetails, sequenceGenerator )
|
||||||
);
|
);
|
||||||
classDetails.forEachAnnotationUsage(
|
classDetails.forEachAnnotationUsage(
|
||||||
TABLE_GENERATOR,
|
TABLE_GENERATOR,
|
||||||
sourceModelContext,
|
sourceModelContext,
|
||||||
this::collectTableGenerator
|
tableGenerator -> collectTableGenerator( classDetails, tableGenerator )
|
||||||
);
|
);
|
||||||
classDetails.forEachAnnotationUsage(
|
classDetails.forEachAnnotationUsage(
|
||||||
GENERIC_GENERATOR,
|
GENERIC_GENERATOR,
|
||||||
|
@ -708,6 +726,51 @@ public class GlobalRegistrationsImpl implements GlobalRegistrations {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void collectIdGenerators(MemberDetails memberDetails) {
|
||||||
|
if ( !bootstrapContext.getJpaCompliance().isGlobalGeneratorScopeEnabled() ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memberDetails.forEachRepeatedAnnotationUsages(
|
||||||
|
SEQUENCE_GENERATOR,
|
||||||
|
sourceModelContext,
|
||||||
|
(sequenceGenerator) -> collectSequenceGenerator( memberDetails, sequenceGenerator )
|
||||||
|
);
|
||||||
|
memberDetails.forEachAnnotationUsage(
|
||||||
|
TABLE_GENERATOR,
|
||||||
|
sourceModelContext,
|
||||||
|
tableGenerator -> collectTableGenerator( memberDetails, tableGenerator )
|
||||||
|
);
|
||||||
|
memberDetails.forEachAnnotationUsage(
|
||||||
|
GENERIC_GENERATOR,
|
||||||
|
sourceModelContext,
|
||||||
|
this::collectGenericGenerator
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Account for implicit naming of sequence and table generators when applied to an entity class per JPA 3.2
|
||||||
|
*/
|
||||||
|
private String determineImplicitGeneratorNameBase(ClassDetails classDetails, GenerationType generationType) {
|
||||||
|
if ( classDetails.getName().endsWith( ".package-info" ) ) {
|
||||||
|
throw new MappingException( String.format(
|
||||||
|
Locale.ROOT,
|
||||||
|
"@%s placed on package (%s) specified no name",
|
||||||
|
generationType == GenerationType.SEQUENCE ? SequenceGenerator.class.getSimpleName() : TableGenerator.class.getSimpleName(),
|
||||||
|
StringHelper.qualifier( classDetails.getName() )
|
||||||
|
) );
|
||||||
|
}
|
||||||
|
final Entity entityAnnotation = classDetails.getDirectAnnotationUsage( ENTITY );
|
||||||
|
if ( entityAnnotation != null ) {
|
||||||
|
final String explicitEntityName = entityAnnotation.name();
|
||||||
|
return StringHelper.isNotEmpty( explicitEntityName )
|
||||||
|
? explicitEntityName
|
||||||
|
: StringHelper.unqualify( classDetails.getName() );
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
// Sequence generator
|
// Sequence generator
|
||||||
|
@ -752,17 +815,35 @@ public class GlobalRegistrationsImpl implements GlobalRegistrations {
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void collectSequenceGenerator(SequenceGenerator usage) {
|
public void collectSequenceGenerator(MemberDetails memberDetails, SequenceGenerator usage) {
|
||||||
collectSequenceGenerator( new SequenceGeneratorRegistration( usage.name(), usage ) );
|
collectSequenceGenerator( memberDetails.getDeclaringType(), usage );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void collectSequenceGenerator(ClassDetails classDetails, SequenceGenerator usage) {
|
||||||
|
final String registrationName;
|
||||||
|
if ( !usage.name().isEmpty() ) {
|
||||||
|
registrationName = usage.name();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
final Entity entityAnnotation = classDetails.getDirectAnnotationUsage( Entity.class );
|
||||||
|
if ( entityAnnotation != null && !entityAnnotation.name().isEmpty() ) {
|
||||||
|
registrationName = entityAnnotation.name();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
registrationName = StringHelper.unqualify( classDetails.getName() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
collectSequenceGenerator( new SequenceGeneratorRegistration( registrationName, usage ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public void collectSequenceGenerator(SequenceGeneratorRegistration generatorRegistration) {
|
public void collectSequenceGenerator(SequenceGeneratorRegistration generatorRegistration) {
|
||||||
checkGeneratorName( generatorRegistration.name() );
|
checkGeneratorName( generatorRegistration.name() );
|
||||||
|
|
||||||
if ( sequenceGeneratorRegistrations == null ) {
|
if ( sequenceGeneratorRegistrations == null ) {
|
||||||
sequenceGeneratorRegistrations = new HashMap<>();
|
sequenceGeneratorRegistrations = new HashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
sequenceGeneratorRegistrations.put( generatorRegistration.name(), generatorRegistration );
|
sequenceGeneratorRegistrations.put( generatorRegistration.name(), generatorRegistration );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -842,16 +923,57 @@ public class GlobalRegistrationsImpl implements GlobalRegistrations {
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void collectTableGenerator(TableGenerator usage) {
|
public void collectTableGenerator(ClassDetails classDetails, TableGenerator usage) {
|
||||||
collectTableGenerator( new TableGeneratorRegistration( usage.name(), usage ) );
|
final TableGeneratorJpaAnnotation generatorAnnotation = new TableGeneratorJpaAnnotation(
|
||||||
|
usage,
|
||||||
|
sourceModelContext
|
||||||
|
);
|
||||||
|
|
||||||
|
final Entity entityAnnotation = classDetails.getDirectAnnotationUsage( Entity.class );
|
||||||
|
final String simpleName;
|
||||||
|
if ( entityAnnotation != null && !entityAnnotation.name().isEmpty() ) {
|
||||||
|
simpleName = entityAnnotation.name();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
simpleName = StringHelper.unqualify( classDetails.getName() );
|
||||||
|
}
|
||||||
|
|
||||||
|
final String registrationName;
|
||||||
|
if ( !usage.name().isEmpty() ) {
|
||||||
|
registrationName = usage.name();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
registrationName = simpleName;
|
||||||
|
}
|
||||||
|
generatorAnnotation.name( registrationName );
|
||||||
|
collectTableGenerator( new TableGeneratorRegistration( registrationName, usage ) );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void collectTableGenerator(MemberDetails memberDetails, TableGenerator usage) {
|
||||||
|
final String registrationName;
|
||||||
|
if ( !usage.name().isEmpty() ) {
|
||||||
|
registrationName = usage.name();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
final Entity entityAnnotation = memberDetails.getDeclaringType().getDirectAnnotationUsage( Entity.class );
|
||||||
|
if ( entityAnnotation != null && !entityAnnotation.name().isEmpty() ) {
|
||||||
|
registrationName = entityAnnotation.name();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
registrationName = StringHelper.unqualify( memberDetails.getDeclaringType().getName() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
collectTableGenerator( new TableGeneratorRegistration( registrationName, usage ) );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void collectTableGenerator(TableGeneratorRegistration generatorRegistration) {
|
public void collectTableGenerator(TableGeneratorRegistration generatorRegistration) {
|
||||||
checkGeneratorName( generatorRegistration.name() );
|
checkGeneratorName( generatorRegistration.name() );
|
||||||
|
|
||||||
if ( tableGeneratorRegistrations == null ) {
|
if ( tableGeneratorRegistrations == null ) {
|
||||||
tableGeneratorRegistrations = new HashMap<>();
|
tableGeneratorRegistrations = new HashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
tableGeneratorRegistrations.put( generatorRegistration.name(), generatorRegistration );
|
tableGeneratorRegistrations.put( generatorRegistration.name(), generatorRegistration );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -879,6 +1001,9 @@ public class GlobalRegistrationsImpl implements GlobalRegistrations {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void collectGenericGenerator(GenericGenerator usage) {
|
public void collectGenericGenerator(GenericGenerator usage) {
|
||||||
|
if ( usage.name().isEmpty() ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
collectGenericGenerator( new GenericGeneratorRegistration( usage.name(), usage ) );
|
collectGenericGenerator( new GenericGeneratorRegistration( usage.name(), usage ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -888,7 +1013,6 @@ public class GlobalRegistrationsImpl implements GlobalRegistrations {
|
||||||
if ( genericGeneratorRegistrations == null ) {
|
if ( genericGeneratorRegistrations == null ) {
|
||||||
genericGeneratorRegistrations = new HashMap<>();
|
genericGeneratorRegistrations = new HashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
genericGeneratorRegistrations.put( generatorRegistration.name(), generatorRegistration );
|
genericGeneratorRegistrations.put( generatorRegistration.name(), generatorRegistration );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
/*
|
||||||
|
* 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.boot.models.spi;
|
||||||
|
|
||||||
|
import org.hibernate.models.spi.MemberDetails;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public interface GlobalRegistrar {
|
||||||
|
void collectIdGenerators(MemberDetails memberDetails);
|
||||||
|
}
|
|
@ -55,4 +55,6 @@ public interface GlobalRegistrations {
|
||||||
Map<String, NamedStoredProcedureQueryRegistration> getNamedStoredProcedureQueryRegistrations();
|
Map<String, NamedStoredProcedureQueryRegistration> getNamedStoredProcedureQueryRegistrations();
|
||||||
|
|
||||||
// todo : named entity graphs
|
// todo : named entity graphs
|
||||||
|
|
||||||
|
<T> T as(Class<T> type);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import java.lang.invoke.MethodHandles;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
|
@ -25,12 +26,14 @@ import org.hibernate.engine.config.spi.ConfigurationService;
|
||||||
import org.hibernate.engine.jdbc.env.spi.IdentifierHelper;
|
import org.hibernate.engine.jdbc.env.spi.IdentifierHelper;
|
||||||
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
|
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
|
||||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
|
import org.hibernate.generator.BeforeExecutionGenerator;
|
||||||
import org.hibernate.generator.GeneratorCreationContext;
|
import org.hibernate.generator.GeneratorCreationContext;
|
||||||
import org.hibernate.id.BulkInsertionCapableIdentifierGenerator;
|
import org.hibernate.id.BulkInsertionCapableIdentifierGenerator;
|
||||||
import org.hibernate.id.IdentifierGenerator;
|
import org.hibernate.id.IdentifierGenerator;
|
||||||
import org.hibernate.id.PersistentIdentifierGenerator;
|
import org.hibernate.id.PersistentIdentifierGenerator;
|
||||||
import org.hibernate.id.SequenceMismatchStrategy;
|
import org.hibernate.id.SequenceMismatchStrategy;
|
||||||
import org.hibernate.internal.CoreMessageLogger;
|
import org.hibernate.internal.CoreMessageLogger;
|
||||||
|
import org.hibernate.mapping.SimpleValue;
|
||||||
import org.hibernate.service.ServiceRegistry;
|
import org.hibernate.service.ServiceRegistry;
|
||||||
import org.hibernate.tool.schema.Action;
|
import org.hibernate.tool.schema.Action;
|
||||||
import org.hibernate.tool.schema.extract.spi.SequenceInformation;
|
import org.hibernate.tool.schema.extract.spi.SequenceInformation;
|
||||||
|
@ -39,6 +42,8 @@ import org.hibernate.type.Type;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
|
import jakarta.persistence.SequenceGenerator;
|
||||||
|
|
||||||
import static java.util.Collections.singleton;
|
import static java.util.Collections.singleton;
|
||||||
import static org.hibernate.id.IdentifierGeneratorHelper.getNamingStrategy;
|
import static org.hibernate.id.IdentifierGeneratorHelper.getNamingStrategy;
|
||||||
import static org.hibernate.id.enhanced.OptimizerFactory.determineImplicitOptimizerName;
|
import static org.hibernate.id.enhanced.OptimizerFactory.determineImplicitOptimizerName;
|
||||||
|
@ -110,7 +115,7 @@ import static org.hibernate.internal.util.config.ConfigurationHelper.getString;
|
||||||
* @author Lukasz Antoniak
|
* @author Lukasz Antoniak
|
||||||
*/
|
*/
|
||||||
public class SequenceStyleGenerator
|
public class SequenceStyleGenerator
|
||||||
implements PersistentIdentifierGenerator, BulkInsertionCapableIdentifierGenerator {
|
implements PersistentIdentifierGenerator, BulkInsertionCapableIdentifierGenerator, BeforeExecutionGenerator {
|
||||||
|
|
||||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
|
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
|
||||||
MethodHandles.lookup(),
|
MethodHandles.lookup(),
|
||||||
|
@ -583,4 +588,27 @@ public class SequenceStyleGenerator
|
||||||
return ( catalog == null || catalog.equals( jdbcEnvironment.getCurrentCatalog() ) )
|
return ( catalog == null || catalog.equals( jdbcEnvironment.getCurrentCatalog() ) )
|
||||||
&& ( schema == null || schema.equals( jdbcEnvironment.getCurrentSchema() ) );
|
&& ( schema == null || schema.equals( jdbcEnvironment.getCurrentSchema() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void applyConfiguration(SequenceGenerator generatorConfig, SimpleValue idValue, BiConsumer<String,String> configCollector) {
|
||||||
|
if ( !generatorConfig.sequenceName().isEmpty() ) {
|
||||||
|
configCollector.accept( SEQUENCE_PARAM, generatorConfig.sequenceName() );
|
||||||
|
}
|
||||||
|
if ( !generatorConfig.catalog().isEmpty() ) {
|
||||||
|
configCollector.accept( CATALOG, generatorConfig.catalog() );
|
||||||
|
}
|
||||||
|
if ( !generatorConfig.schema().isEmpty() ) {
|
||||||
|
configCollector.accept( SCHEMA, generatorConfig.schema() );
|
||||||
|
}
|
||||||
|
if ( !generatorConfig.options().isEmpty() ) {
|
||||||
|
configCollector.accept( OPTIONS, generatorConfig.options() );
|
||||||
|
}
|
||||||
|
|
||||||
|
configCollector.accept( INITIAL_PARAM, Integer.toString( generatorConfig.initialValue() ) );
|
||||||
|
if ( generatorConfig.allocationSize() == 50 ) {
|
||||||
|
// don't do anything - assuming a proper default is already set
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
configCollector.accept( INCREMENT_PARAM, Integer.toString( generatorConfig.allocationSize() ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ import java.sql.SQLException;
|
||||||
import java.sql.Types;
|
import java.sql.Types;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
import org.hibernate.LockOptions;
|
import org.hibernate.LockOptions;
|
||||||
|
@ -43,9 +44,11 @@ import org.hibernate.id.IdentifierGeneratorHelper;
|
||||||
import org.hibernate.id.IntegralDataTypeHolder;
|
import org.hibernate.id.IntegralDataTypeHolder;
|
||||||
import org.hibernate.id.PersistentIdentifierGenerator;
|
import org.hibernate.id.PersistentIdentifierGenerator;
|
||||||
import org.hibernate.internal.CoreMessageLogger;
|
import org.hibernate.internal.CoreMessageLogger;
|
||||||
|
import org.hibernate.internal.util.config.ConfigurationHelper;
|
||||||
import org.hibernate.jdbc.AbstractReturningWork;
|
import org.hibernate.jdbc.AbstractReturningWork;
|
||||||
import org.hibernate.mapping.Column;
|
import org.hibernate.mapping.Column;
|
||||||
import org.hibernate.mapping.PrimaryKey;
|
import org.hibernate.mapping.PrimaryKey;
|
||||||
|
import org.hibernate.mapping.SimpleValue;
|
||||||
import org.hibernate.mapping.Table;
|
import org.hibernate.mapping.Table;
|
||||||
import org.hibernate.service.ServiceRegistry;
|
import org.hibernate.service.ServiceRegistry;
|
||||||
import org.hibernate.type.BasicTypeRegistry;
|
import org.hibernate.type.BasicTypeRegistry;
|
||||||
|
@ -55,6 +58,7 @@ import org.hibernate.type.Type;
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
import static java.util.Collections.singletonMap;
|
import static java.util.Collections.singletonMap;
|
||||||
|
import static org.hibernate.boot.model.internal.GeneratorBinder.applyIfNotEmpty;
|
||||||
import static org.hibernate.id.IdentifierGeneratorHelper.getNamingStrategy;
|
import static org.hibernate.id.IdentifierGeneratorHelper.getNamingStrategy;
|
||||||
import static org.hibernate.id.enhanced.OptimizerFactory.determineImplicitOptimizerName;
|
import static org.hibernate.id.enhanced.OptimizerFactory.determineImplicitOptimizerName;
|
||||||
import static org.hibernate.internal.util.StringHelper.isEmpty;
|
import static org.hibernate.internal.util.StringHelper.isEmpty;
|
||||||
|
@ -225,6 +229,7 @@ public class TableGenerator implements PersistentIdentifierGenerator {
|
||||||
private String contributor;
|
private String contributor;
|
||||||
|
|
||||||
private String options;
|
private String options;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Type mapping for the identifier.
|
* Type mapping for the identifier.
|
||||||
*
|
*
|
||||||
|
@ -723,4 +728,35 @@ public class TableGenerator implements PersistentIdentifierGenerator {
|
||||||
updateQuery = buildUpdateQuery( formattedPhysicalTableName, context );
|
updateQuery = buildUpdateQuery( formattedPhysicalTableName, context );
|
||||||
insertQuery = buildInsertQuery( formattedPhysicalTableName, context );
|
insertQuery = buildInsertQuery( formattedPhysicalTableName, context );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void applyConfiguration(
|
||||||
|
jakarta.persistence.TableGenerator generatorConfig,
|
||||||
|
SimpleValue idValue,
|
||||||
|
Map<String, String> configuration) {
|
||||||
|
applyConfiguration( generatorConfig, idValue, configuration::put );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void applyConfiguration(
|
||||||
|
jakarta.persistence.TableGenerator generatorConfig,
|
||||||
|
SimpleValue idValue,
|
||||||
|
BiConsumer<String, String> configurationCollector) {
|
||||||
|
configurationCollector.accept( CONFIG_PREFER_SEGMENT_PER_ENTITY, "true" );
|
||||||
|
|
||||||
|
applyIfNotEmpty( TABLE_PARAM, generatorConfig.table(), configurationCollector );
|
||||||
|
applyIfNotEmpty( CATALOG, generatorConfig.catalog(), configurationCollector );
|
||||||
|
applyIfNotEmpty( SCHEMA, generatorConfig.schema(), configurationCollector );
|
||||||
|
applyIfNotEmpty( OPTIONS, generatorConfig.options(), configurationCollector );
|
||||||
|
|
||||||
|
applyIfNotEmpty( SEGMENT_COLUMN_PARAM, generatorConfig.pkColumnName(), configurationCollector );
|
||||||
|
applyIfNotEmpty( SEGMENT_VALUE_PARAM, generatorConfig.pkColumnValue(), configurationCollector );
|
||||||
|
applyIfNotEmpty( VALUE_COLUMN_PARAM, generatorConfig.valueColumnName(), configurationCollector );
|
||||||
|
|
||||||
|
configurationCollector.accept( INITIAL_PARAM, Integer.toString( generatorConfig.initialValue() + 1 ) );
|
||||||
|
if ( generatorConfig.allocationSize() == 50 ) {
|
||||||
|
// don't do anything - assuming a proper default is already set
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
configurationCollector.accept( INCREMENT_PARAM, Integer.toString( generatorConfig.allocationSize() ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ import org.hibernate.generator.BeforeExecutionGenerator;
|
||||||
import org.hibernate.generator.EventType;
|
import org.hibernate.generator.EventType;
|
||||||
import org.hibernate.generator.EventTypeSets;
|
import org.hibernate.generator.EventTypeSets;
|
||||||
import org.hibernate.generator.GeneratorCreationContext;
|
import org.hibernate.generator.GeneratorCreationContext;
|
||||||
import org.hibernate.generator.BeforeExecutionGenerator;
|
import org.hibernate.models.spi.MemberDetails;
|
||||||
import org.hibernate.type.descriptor.java.UUIDJavaType;
|
import org.hibernate.type.descriptor.java.UUIDJavaType;
|
||||||
import org.hibernate.type.descriptor.java.UUIDJavaType.ValueTransformer;
|
import org.hibernate.type.descriptor.java.UUIDJavaType.ValueTransformer;
|
||||||
|
|
||||||
|
@ -49,7 +49,47 @@ public class UuidGenerator implements BeforeExecutionGenerator {
|
||||||
valueTransformer = determineProperTransformer( memberType );
|
valueTransformer = determineProperTransformer( memberType );
|
||||||
}
|
}
|
||||||
|
|
||||||
private UuidGenerator(
|
/**
|
||||||
|
* This form is used when there is no {@code @UuidGenerator} but we know we want this generator
|
||||||
|
*/
|
||||||
|
@Internal
|
||||||
|
public UuidGenerator(
|
||||||
|
org.hibernate.annotations.UuidGenerator config,
|
||||||
|
MemberDetails memberDetails) {
|
||||||
|
generator = determineValueGenerator( config, memberDetails );
|
||||||
|
|
||||||
|
final Class<?> memberType = memberDetails.getType().determineRawClass().toJavaClass();
|
||||||
|
valueTransformer = determineProperTransformer( memberType );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static UuidValueGenerator determineValueGenerator(
|
||||||
|
org.hibernate.annotations.UuidGenerator config,
|
||||||
|
MemberDetails memberDetails) {
|
||||||
|
if ( config != null ) {
|
||||||
|
if ( config.algorithm() != UuidValueGenerator.class ) {
|
||||||
|
if ( config.style() != AUTO ) {
|
||||||
|
throw new MappingException(
|
||||||
|
String.format(
|
||||||
|
Locale.ROOT,
|
||||||
|
"Style [%s] should not be specified with custom UUID value generator : %s.%s",
|
||||||
|
config.style().name(),
|
||||||
|
memberDetails.getDeclaringType().getName(),
|
||||||
|
memberDetails.getName()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return instantiateCustomGenerator( config.algorithm() );
|
||||||
|
}
|
||||||
|
else if ( config.style() == TIME ) {
|
||||||
|
return new CustomVersionOneStrategy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return StandardRandomStrategy.INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Internal
|
||||||
|
public UuidGenerator(
|
||||||
org.hibernate.annotations.UuidGenerator config,
|
org.hibernate.annotations.UuidGenerator config,
|
||||||
Member idMember) {
|
Member idMember) {
|
||||||
if ( config.algorithm() != UuidValueGenerator.class ) {
|
if ( config.algorithm() != UuidValueGenerator.class ) {
|
||||||
|
|
|
@ -570,6 +570,18 @@ public final class ConfigurationHelper {
|
||||||
.getPreferredSqlTypeCodeForArray();
|
.getPreferredSqlTypeCodeForArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void setIfNotEmpty(String value, String settingName, Map<String, String> configuration) {
|
||||||
|
if ( StringHelper.isNotEmpty( value ) ) {
|
||||||
|
configuration.put( settingName, value );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setIfNotNull(Object value, String settingName, Map<String, Object> configuration) {
|
||||||
|
if ( value != null ) {
|
||||||
|
configuration.put( settingName, value );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static class TypeCodeConverter implements ConfigurationService.Converter<Integer> {
|
private static class TypeCodeConverter implements ConfigurationService.Converter<Integer> {
|
||||||
|
|
||||||
public static final TypeCodeConverter INSTANCE = new TypeCodeConverter();
|
public static final TypeCodeConverter INSTANCE = new TypeCodeConverter();
|
||||||
|
|
|
@ -87,7 +87,7 @@ public class IdClassAndAssociationsTest {
|
||||||
@Table(name = "course_enrollment")
|
@Table(name = "course_enrollment")
|
||||||
public static class CourseEnrollment {
|
public static class CourseEnrollment {
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
@GeneratedValue(strategy = GenerationType.SEQUENCE)
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
@Column(name = "course")
|
@Column(name = "course")
|
||||||
|
@ -123,7 +123,7 @@ public class IdClassAndAssociationsTest {
|
||||||
@Table(name = "units")
|
@Table(name = "units")
|
||||||
public static class Unit {
|
public static class Unit {
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
@GeneratedValue(strategy = GenerationType.SEQUENCE)
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
private String name;
|
private String name;
|
||||||
|
@ -140,7 +140,7 @@ public class IdClassAndAssociationsTest {
|
||||||
@Table(name = "users")
|
@Table(name = "users")
|
||||||
public static class User {
|
public static class User {
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
@GeneratedValue(strategy = GenerationType.SEQUENCE)
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
@Column(name = "first_name")
|
@Column(name = "first_name")
|
||||||
|
|
|
@ -12,6 +12,8 @@ import org.hibernate.id.enhanced.NoopOptimizer;
|
||||||
import org.hibernate.id.enhanced.PooledOptimizer;
|
import org.hibernate.id.enhanced.PooledOptimizer;
|
||||||
import org.hibernate.id.enhanced.SequenceStyleGenerator;
|
import org.hibernate.id.enhanced.SequenceStyleGenerator;
|
||||||
import org.hibernate.id.enhanced.TableGenerator;
|
import org.hibernate.id.enhanced.TableGenerator;
|
||||||
|
import org.hibernate.orm.test.annotations.id.generationmappings.sub.DedicatedSequenceEntity1;
|
||||||
|
import org.hibernate.orm.test.annotations.id.generationmappings.sub.DedicatedSequenceEntity2;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
import org.hibernate.testing.orm.junit.JiraKey;
|
import org.hibernate.testing.orm.junit.JiraKey;
|
||||||
import org.hibernate.testing.orm.junit.DomainModel;
|
import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
|
@ -130,7 +132,8 @@ public class NewGeneratorMappingsTest {
|
||||||
@JiraKey(value = "HHH-6790")
|
@JiraKey(value = "HHH-6790")
|
||||||
public void testSequencePerEntity(SessionFactoryScope scope) {
|
public void testSequencePerEntity(SessionFactoryScope scope) {
|
||||||
// Checking first entity.
|
// Checking first entity.
|
||||||
EntityPersister persister = scope.getSessionFactory().getRuntimeMetamodels().getMappingMetamodel().getEntityDescriptor(DedicatedSequenceEntity1.class.getName());
|
EntityPersister persister = scope.getSessionFactory().getRuntimeMetamodels().getMappingMetamodel().getEntityDescriptor(
|
||||||
|
DedicatedSequenceEntity1.class.getName());
|
||||||
IdentifierGenerator generator = persister.getIdentifierGenerator();
|
IdentifierGenerator generator = persister.getIdentifierGenerator();
|
||||||
assertTrue( SequenceStyleGenerator.class.isInstance( generator ) );
|
assertTrue( SequenceStyleGenerator.class.isInstance( generator ) );
|
||||||
SequenceStyleGenerator seqGenerator = (SequenceStyleGenerator) generator;
|
SequenceStyleGenerator seqGenerator = (SequenceStyleGenerator) generator;
|
||||||
|
|
|
@ -2,9 +2,9 @@
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
*
|
*
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
* 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>.
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
|
||||||
*/
|
*/
|
||||||
package org.hibernate.orm.test.annotations.id.generationmappings;
|
package org.hibernate.orm.test.annotations.id.generationmappings.sub;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import jakarta.persistence.Entity;
|
import jakarta.persistence.Entity;
|
|
@ -2,9 +2,9 @@
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
*
|
*
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
* 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>.
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
|
||||||
*/
|
*/
|
||||||
package org.hibernate.orm.test.annotations.id.generationmappings;
|
package org.hibernate.orm.test.annotations.id.generationmappings.sub;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import jakarta.persistence.Entity;
|
import jakarta.persistence.Entity;
|
|
@ -2,7 +2,7 @@
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
*
|
*
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
* 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>.
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
|
||||||
*/
|
*/
|
||||||
@GenericGenerator(name = "SequencePerEntityGenerator",
|
@GenericGenerator(name = "SequencePerEntityGenerator",
|
||||||
strategy = "org.hibernate.id.enhanced.SequenceStyleGenerator",
|
strategy = "org.hibernate.id.enhanced.SequenceStyleGenerator",
|
||||||
|
@ -12,7 +12,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
)
|
)
|
||||||
package org.hibernate.orm.test.annotations.id.generationmappings;
|
package org.hibernate.orm.test.annotations.id.generationmappings.sub;
|
||||||
|
|
||||||
import org.hibernate.annotations.GenericGenerator;
|
import org.hibernate.annotations.GenericGenerator;
|
||||||
import org.hibernate.annotations.Parameter;
|
import org.hibernate.annotations.Parameter;
|
|
@ -0,0 +1,141 @@
|
||||||
|
/*
|
||||||
|
* 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.orm.test.annotations.id.generators;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.GeneratedValue;
|
||||||
|
import jakarta.persistence.GenerationType;
|
||||||
|
import jakarta.persistence.Id;
|
||||||
|
import jakarta.persistence.Table;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("JUnitMalformedDeclaration")
|
||||||
|
public class SimpleIdTests {
|
||||||
|
@Test
|
||||||
|
@DomainModel(annotatedClasses = Entity1.class)
|
||||||
|
@SessionFactory
|
||||||
|
void testSimpleAutoFallback(SessionFactoryScope sessions) {
|
||||||
|
sessions.inTransaction( (session) -> {
|
||||||
|
session.persist( new Entity1( "1" ) );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DomainModel(annotatedClasses = Entity2.class)
|
||||||
|
@SessionFactory
|
||||||
|
void testSimpleTableFallback(SessionFactoryScope sessions) {
|
||||||
|
sessions.inTransaction( (session) -> {
|
||||||
|
session.persist( new Entity2( "2" ) );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DomainModel(annotatedClasses = Entity3.class)
|
||||||
|
@SessionFactory
|
||||||
|
void testSimpleNamedGenerator(SessionFactoryScope sessions) {
|
||||||
|
sessions.inTransaction( (session) -> {
|
||||||
|
session.persist( new Entity3( "3" ) );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DomainModel(annotatedClasses = Entity4.class)
|
||||||
|
@SessionFactory
|
||||||
|
void testSimpleUuidFallback(SessionFactoryScope sessions) {
|
||||||
|
sessions.inTransaction( (session) -> {
|
||||||
|
session.persist( new Entity4( "4" ) );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DomainModel(annotatedClasses = Entity5.class)
|
||||||
|
@SessionFactory
|
||||||
|
void testSimpleUuidAsStringFallback(SessionFactoryScope sessions) {
|
||||||
|
sessions.inTransaction( (session) -> {
|
||||||
|
session.persist( new Entity5( "5" ) );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name="Entity1")
|
||||||
|
@Table(name="Entity1")
|
||||||
|
public static class Entity1 {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
private Integer id;
|
||||||
|
private String name;
|
||||||
|
public Entity1() {
|
||||||
|
}
|
||||||
|
public Entity1(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name="Entity2")
|
||||||
|
@Table(name="Entity2")
|
||||||
|
public static class Entity2 {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.TABLE)
|
||||||
|
private Integer id;
|
||||||
|
private String name;
|
||||||
|
public Entity2() {
|
||||||
|
}
|
||||||
|
public Entity2(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name="Entity3")
|
||||||
|
@Table(name="Entity3")
|
||||||
|
public static class Entity3 {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(generator = "increment")
|
||||||
|
private Integer id;
|
||||||
|
private String name;
|
||||||
|
public Entity3() {
|
||||||
|
}
|
||||||
|
public Entity3(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name="Entity4")
|
||||||
|
@Table(name="Entity4")
|
||||||
|
public static class Entity4 {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
private UUID id;
|
||||||
|
private String name;
|
||||||
|
public Entity4() {
|
||||||
|
}
|
||||||
|
public Entity4(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name="Entity5")
|
||||||
|
@Table(name="Entity5")
|
||||||
|
public static class Entity5 {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.UUID)
|
||||||
|
private String id;
|
||||||
|
private String name;
|
||||||
|
public Entity5() {
|
||||||
|
}
|
||||||
|
public Entity5(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,177 @@
|
||||||
|
/*
|
||||||
|
* 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.orm.test.annotations.id.generators;
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
import org.hibernate.boot.Metadata;
|
||||||
|
import org.hibernate.boot.MetadataSources;
|
||||||
|
import org.hibernate.boot.registry.StandardServiceRegistry;
|
||||||
|
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||||
|
import org.hibernate.cfg.AvailableSettings;
|
||||||
|
import org.hibernate.generator.Generator;
|
||||||
|
import org.hibernate.mapping.RootClass;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.GeneratedValue;
|
||||||
|
import jakarta.persistence.Id;
|
||||||
|
import jakarta.persistence.SequenceGenerator;
|
||||||
|
import jakarta.persistence.TableGenerator;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public class UnnamedGeneratorTests {
|
||||||
|
@Test
|
||||||
|
void testAutoWithNoGenerator() {
|
||||||
|
checkSequence( Entity1.class, "Entity1_seq" );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testAutoWithSequenceGenerator() {
|
||||||
|
checkSequence( Entity2.class, "Entity2_seq" );
|
||||||
|
checkSequence( Entity3.class, "my_seq" );
|
||||||
|
checkSequence( Entity4.class, "another_seq" );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testAutoWithTableGenerator() {
|
||||||
|
checkTableGenerator( Entity5.class, "hibernate_sequences", "Entity5" );
|
||||||
|
checkTableGenerator( Entity6.class, "my_sequences", "Entity6" );
|
||||||
|
checkTableGenerator( Entity7.class, "sequences_table", "Entity7" );
|
||||||
|
checkTableGenerator( Entity8.class, "sequences_table", "ent_8" );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkSequence(Class<?> entityClass, String expectedDbName) {
|
||||||
|
// strictly-global = false
|
||||||
|
withGenerator( entityClass, false, (generator) -> {
|
||||||
|
final String name = SEQUENCE_NAME_EXTRACTOR.apply( generator );
|
||||||
|
assertThat( name ).isEqualToIgnoringCase( expectedDbName );
|
||||||
|
} );
|
||||||
|
|
||||||
|
// strictly-global = true
|
||||||
|
withGenerator( entityClass, true, (generator) -> {
|
||||||
|
final String name = SEQUENCE_NAME_EXTRACTOR.apply( generator );
|
||||||
|
assertThat( name ).isEqualToIgnoringCase( expectedDbName );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkTableGenerator(Class<?> entityClass, String expectedTableName, String expectedSegmentName) {
|
||||||
|
// strictly-global = false
|
||||||
|
withGenerator( entityClass, false, (generator) -> {
|
||||||
|
final org.hibernate.id.enhanced.TableGenerator tableGenerator = (org.hibernate.id.enhanced.TableGenerator) generator;
|
||||||
|
assertThat( tableGenerator.getTableName() ).isEqualToIgnoringCase( expectedTableName );
|
||||||
|
assertThat( tableGenerator.getSegmentValue() ).isEqualTo( expectedSegmentName );
|
||||||
|
} );
|
||||||
|
|
||||||
|
// strictly-global = true
|
||||||
|
withGenerator( entityClass, true, (generator) -> {
|
||||||
|
final org.hibernate.id.enhanced.TableGenerator tableGenerator = (org.hibernate.id.enhanced.TableGenerator) generator;
|
||||||
|
assertThat( tableGenerator.getTableName() ).isEqualToIgnoringCase( expectedTableName );
|
||||||
|
assertThat( tableGenerator.getSegmentValue() ).isEqualTo( expectedSegmentName );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void withGenerator(Class<?> entityClass, boolean strictlyGlobal, Consumer<Generator> checks) {
|
||||||
|
try (StandardServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
|
||||||
|
.applySetting( AvailableSettings.JPA_ID_GENERATOR_GLOBAL_SCOPE_COMPLIANCE, strictlyGlobal )
|
||||||
|
.build()) {
|
||||||
|
final Metadata metadata = new MetadataSources( serviceRegistry )
|
||||||
|
.addAnnotatedClasses( entityClass )
|
||||||
|
.buildMetadata();
|
||||||
|
final RootClass entityBinding = metadata.getEntityBinding( entityClass.getName() ).getRootClass();
|
||||||
|
final Generator generator = entityBinding.getIdentifier().createGenerator(
|
||||||
|
metadata.getDatabase().getDialect(),
|
||||||
|
entityBinding,
|
||||||
|
entityBinding.getIdentifierProperty()
|
||||||
|
);
|
||||||
|
|
||||||
|
checks.accept( generator );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name="Entity1")
|
||||||
|
public static class Entity1 {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
private Integer id;
|
||||||
|
private String name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name="Entity2")
|
||||||
|
public static class Entity2 {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
@SequenceGenerator
|
||||||
|
private Integer id;
|
||||||
|
private String name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name="Entity3")
|
||||||
|
public static class Entity3 {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
@SequenceGenerator(sequenceName = "my_seq")
|
||||||
|
private Integer id;
|
||||||
|
private String name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name="Entity4")
|
||||||
|
@SequenceGenerator(sequenceName = "another_seq")
|
||||||
|
public static class Entity4 {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
private Integer id;
|
||||||
|
private String name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name="Entity5")
|
||||||
|
public static class Entity5 {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
@TableGenerator
|
||||||
|
private Integer id;
|
||||||
|
private String name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name="Entity6")
|
||||||
|
public static class Entity6 {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
@TableGenerator(table = "my_sequences")
|
||||||
|
private Integer id;
|
||||||
|
private String name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name="Entity7")
|
||||||
|
@TableGenerator(table = "sequences_table")
|
||||||
|
public static class Entity7 {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
private Integer id;
|
||||||
|
private String name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name="Entity8")
|
||||||
|
@TableGenerator(table = "sequences_table", pkColumnValue = "ent_8")
|
||||||
|
public static class Entity8 {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
private Integer id;
|
||||||
|
private String name;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final Function<Generator,String> SEQUENCE_NAME_EXTRACTOR = (generator) -> {
|
||||||
|
return ( (org.hibernate.id.enhanced.SequenceStyleGenerator) generator ).getDatabaseStructure().getPhysicalName().getObjectName().getText();
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,45 +1,49 @@
|
||||||
package org.hibernate.orm.test.annotations.id.generators.entity;
|
package org.hibernate.orm.test.annotations.id.generators.entity;
|
||||||
|
|
||||||
|
import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import jakarta.persistence.Entity;
|
import jakarta.persistence.Entity;
|
||||||
import jakarta.persistence.GeneratedValue;
|
import jakarta.persistence.GeneratedValue;
|
||||||
import jakarta.persistence.Id;
|
import jakarta.persistence.Id;
|
||||||
import jakarta.persistence.SequenceGenerator;
|
import jakarta.persistence.SequenceGenerator;
|
||||||
import jakarta.persistence.TableGenerator;
|
import jakarta.persistence.TableGenerator;
|
||||||
import org.hibernate.testing.orm.junit.DomainModel;
|
|
||||||
import org.hibernate.testing.orm.junit.FailureExpected;
|
|
||||||
import org.hibernate.testing.orm.junit.Jira;
|
|
||||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
|
||||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
@SessionFactory
|
@SessionFactory
|
||||||
@DomainModel(annotatedClasses =
|
@DomainModel(
|
||||||
{ClassLevelGeneratorTest.EntityWithAnonSequenceGenerator.class,
|
annotatedClasses = {
|
||||||
ClassLevelGeneratorTest.EntityWithAnonTableGenerator.class})
|
ClassLevelGeneratorTest.EntityWithAnonSequenceGenerator.class,
|
||||||
@FailureExpected( reason = "Support for unnamed generators is not implemented yet" )
|
ClassLevelGeneratorTest.EntityWithAnonTableGenerator.class
|
||||||
@Jira( "https://hibernate.atlassian.net/browse/HHH-18498" )
|
}
|
||||||
|
)
|
||||||
public class ClassLevelGeneratorTest {
|
public class ClassLevelGeneratorTest {
|
||||||
@Test
|
@Test
|
||||||
void testAnonGenerator(SessionFactoryScope scope) {
|
void testAnonGenerator(SessionFactoryScope scope) {
|
||||||
|
// this won't work with global scoping due to
|
||||||
|
assertThat( scope.getSessionFactory().getSessionFactoryOptions().getJpaCompliance().isGlobalGeneratorScopeEnabled() ).isFalse();
|
||||||
|
|
||||||
scope.inSession(s-> {
|
scope.inSession(s-> {
|
||||||
EntityWithAnonSequenceGenerator entity1 = new EntityWithAnonSequenceGenerator();
|
EntityWithAnonSequenceGenerator entity1 = new EntityWithAnonSequenceGenerator();
|
||||||
EntityWithAnonTableGenerator entity2 = new EntityWithAnonTableGenerator();
|
EntityWithAnonTableGenerator entity2 = new EntityWithAnonTableGenerator();
|
||||||
s.persist(entity1);
|
s.persist(entity1);
|
||||||
s.persist(entity2);
|
s.persist(entity2);
|
||||||
assertEquals(42, entity1.id);
|
assertEquals(42, entity1.id);
|
||||||
assertEquals(69, entity2.id);
|
assertEquals(70, entity2.id);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@Entity
|
@Entity(name = "EntityWithAnonSequenceGenerator")
|
||||||
@SequenceGenerator(initialValue = 42)
|
@SequenceGenerator(initialValue = 42)
|
||||||
static class EntityWithAnonSequenceGenerator {
|
static class EntityWithAnonSequenceGenerator {
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue
|
@GeneratedValue
|
||||||
long id;
|
long id;
|
||||||
}
|
}
|
||||||
@Entity
|
@Entity(name = "EntityWithAnonTableGenerator")
|
||||||
@TableGenerator(initialValue = 69)
|
@TableGenerator(initialValue = 69)
|
||||||
static class EntityWithAnonTableGenerator {
|
static class EntityWithAnonTableGenerator {
|
||||||
@Id
|
@Id
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
* 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.orm.test.annotations.id.generators.entity;
|
||||||
|
|
||||||
|
import org.hibernate.cfg.AvailableSettings;
|
||||||
|
|
||||||
|
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.SessionFactoryScope;
|
||||||
|
import org.hibernate.testing.orm.junit.Setting;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.GeneratedValue;
|
||||||
|
import jakarta.persistence.Id;
|
||||||
|
import jakarta.persistence.SequenceGenerator;
|
||||||
|
import jakarta.persistence.TableGenerator;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
@SessionFactory
|
||||||
|
@ServiceRegistry(settings = @Setting(name= AvailableSettings.JPA_ID_GENERATOR_GLOBAL_SCOPE_COMPLIANCE, value = "true"))
|
||||||
|
@DomainModel(annotatedClasses = {
|
||||||
|
DefaultedGeneratorWithGlobalScopeTest.EntityWithAnonSequenceGenerator.class,
|
||||||
|
DefaultedGeneratorWithGlobalScopeTest.EntityWithAnonTableGenerator.class
|
||||||
|
})
|
||||||
|
public class DefaultedGeneratorWithGlobalScopeTest {
|
||||||
|
@Test
|
||||||
|
void testAnonGenerator(SessionFactoryScope scope) {
|
||||||
|
scope.inSession(s-> {
|
||||||
|
EntityWithAnonSequenceGenerator entity1 = new EntityWithAnonSequenceGenerator();
|
||||||
|
EntityWithAnonTableGenerator entity2 = new EntityWithAnonTableGenerator();
|
||||||
|
s.persist(entity1);
|
||||||
|
s.persist(entity2);
|
||||||
|
assertEquals(42, entity1.id);
|
||||||
|
assertEquals(70, entity2.id);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
@Entity(name = "EntityWithAnonSequenceGenerator")
|
||||||
|
@SequenceGenerator(initialValue = 42)
|
||||||
|
static class EntityWithAnonSequenceGenerator {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
long id;
|
||||||
|
}
|
||||||
|
@Entity(name = "EntityWithAnonTableGenerator")
|
||||||
|
@TableGenerator(initialValue = 69)
|
||||||
|
static class EntityWithAnonTableGenerator {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
long id;
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,8 +18,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
@DomainModel(annotatedClasses =
|
@DomainModel(annotatedClasses =
|
||||||
{FieldLevelGeneratorTest.EntityWithAnonSequenceGenerator.class,
|
{FieldLevelGeneratorTest.EntityWithAnonSequenceGenerator.class,
|
||||||
FieldLevelGeneratorTest.EntityWithAnonTableGenerator.class})
|
FieldLevelGeneratorTest.EntityWithAnonTableGenerator.class})
|
||||||
@FailureExpected( reason = "Support for unnamed generators is not implemented yet" )
|
|
||||||
@Jira( "https://hibernate.atlassian.net/browse/HHH-18498" )
|
|
||||||
public class FieldLevelGeneratorTest {
|
public class FieldLevelGeneratorTest {
|
||||||
@Test
|
@Test
|
||||||
void testAnonGenerator(SessionFactoryScope scope) {
|
void testAnonGenerator(SessionFactoryScope scope) {
|
||||||
|
@ -29,17 +27,19 @@ public class FieldLevelGeneratorTest {
|
||||||
s.persist(entity1);
|
s.persist(entity1);
|
||||||
s.persist(entity2);
|
s.persist(entity2);
|
||||||
assertEquals(42, entity1.id);
|
assertEquals(42, entity1.id);
|
||||||
assertEquals(69, entity2.id);
|
assertEquals(70, entity2.id);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@Entity
|
|
||||||
|
@Entity(name = "EntityWithAnonSequenceGenerator")
|
||||||
static class EntityWithAnonSequenceGenerator {
|
static class EntityWithAnonSequenceGenerator {
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue
|
@GeneratedValue
|
||||||
@SequenceGenerator(initialValue = 42)
|
@SequenceGenerator(initialValue = 42)
|
||||||
long id;
|
long id;
|
||||||
}
|
}
|
||||||
@Entity
|
|
||||||
|
@Entity(name = "EntityWithAnonTableGenerator")
|
||||||
static class EntityWithAnonTableGenerator {
|
static class EntityWithAnonTableGenerator {
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue
|
@GeneratedValue
|
||||||
|
|
|
@ -2,6 +2,7 @@ package org.hibernate.orm.test.annotations.id.generators.pkg;
|
||||||
|
|
||||||
import jakarta.persistence.Entity;
|
import jakarta.persistence.Entity;
|
||||||
import jakarta.persistence.GeneratedValue;
|
import jakarta.persistence.GeneratedValue;
|
||||||
|
import jakarta.persistence.GenerationType;
|
||||||
import jakarta.persistence.Id;
|
import jakarta.persistence.Id;
|
||||||
import org.hibernate.testing.orm.junit.DomainModel;
|
import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
import org.hibernate.testing.orm.junit.FailureExpected;
|
import org.hibernate.testing.orm.junit.FailureExpected;
|
||||||
|
@ -13,33 +14,52 @@ import org.junit.jupiter.api.Test;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
@SessionFactory
|
@SessionFactory
|
||||||
@DomainModel(annotatedClasses =
|
@DomainModel(annotatedClasses = {
|
||||||
{PackageLevelGeneratorTest.EntityWithAnonSequenceGenerator.class,
|
PackageLevelGeneratorTest.EntityWithDefaultedPackageGenerator.class,
|
||||||
PackageLevelGeneratorTest.EntityWithAnonTableGenerator.class})
|
PackageLevelGeneratorTest.EntityWithDefaultedPackageGenerator2.class,
|
||||||
@FailureExpected( reason = "Support for unnamed generators is not implemented yet" )
|
PackageLevelGeneratorTest.EntityWithDefaultedPackageGenerator3.class,
|
||||||
@Jira( "https://hibernate.atlassian.net/browse/HHH-18498" )
|
PackageLevelGeneratorTest.EntityWithDefaultedPackageGenerator4.class
|
||||||
|
})
|
||||||
public class PackageLevelGeneratorTest {
|
public class PackageLevelGeneratorTest {
|
||||||
@Test
|
@Test
|
||||||
void testAnonGenerator(SessionFactoryScope scope) {
|
void testAnonGenerator(SessionFactoryScope scope) {
|
||||||
scope.inSession(s-> {
|
scope.inSession(s-> {
|
||||||
EntityWithAnonSequenceGenerator entity1 = new EntityWithAnonSequenceGenerator();
|
EntityWithDefaultedPackageGenerator entity1 = new EntityWithDefaultedPackageGenerator();
|
||||||
EntityWithAnonTableGenerator entity2 = new EntityWithAnonTableGenerator();
|
EntityWithDefaultedPackageGenerator2 entity2 = new EntityWithDefaultedPackageGenerator2();
|
||||||
|
EntityWithDefaultedPackageGenerator3 entity3 = new EntityWithDefaultedPackageGenerator3();
|
||||||
|
EntityWithDefaultedPackageGenerator4 entity4 = new EntityWithDefaultedPackageGenerator4();
|
||||||
s.persist(entity1);
|
s.persist(entity1);
|
||||||
s.persist(entity2);
|
s.persist(entity2);
|
||||||
|
s.persist(entity3);
|
||||||
|
s.persist(entity4);
|
||||||
assertEquals(42, entity1.id);
|
assertEquals(42, entity1.id);
|
||||||
assertEquals(69, entity2.id);
|
assertEquals(42, entity2.id);
|
||||||
|
assertEquals(42, entity3.id);
|
||||||
|
assertEquals(70, entity4.id);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@Entity
|
@Entity(name="EntityWithDefaultedPackageGenerator")
|
||||||
static class EntityWithAnonSequenceGenerator {
|
static class EntityWithDefaultedPackageGenerator {
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue
|
@GeneratedValue
|
||||||
long id;
|
long id;
|
||||||
}
|
}
|
||||||
@Entity
|
@Entity(name = "EntityWithDefaultedPackageGenerator2")
|
||||||
static class EntityWithAnonTableGenerator {
|
static class EntityWithDefaultedPackageGenerator2 {
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue
|
@GeneratedValue
|
||||||
long id;
|
long id;
|
||||||
}
|
}
|
||||||
|
@Entity(name = "EntityWithDefaultedPackageGenerator3")
|
||||||
|
static class EntityWithDefaultedPackageGenerator3 {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.SEQUENCE)
|
||||||
|
long id;
|
||||||
|
}
|
||||||
|
@Entity(name = "EntityWithDefaultedPackageGenerator4")
|
||||||
|
static class EntityWithDefaultedPackageGenerator4 {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.TABLE)
|
||||||
|
long id;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,8 +14,8 @@ import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
import org.hibernate.testing.orm.junit.RequiresDialectFeature;
|
import org.hibernate.testing.orm.junit.RequiresDialectFeature;
|
||||||
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.orm.test.annotations.id.generationmappings.DedicatedSequenceEntity1;
|
import org.hibernate.orm.test.annotations.id.generationmappings.sub.DedicatedSequenceEntity1;
|
||||||
import org.hibernate.orm.test.annotations.id.generationmappings.DedicatedSequenceEntity2;
|
import org.hibernate.orm.test.annotations.id.generationmappings.sub.DedicatedSequenceEntity2;
|
||||||
import org.hibernate.orm.test.annotations.id.sequences.entities.Ball;
|
import org.hibernate.orm.test.annotations.id.sequences.entities.Ball;
|
||||||
import org.hibernate.orm.test.annotations.id.sequences.entities.BreakDance;
|
import org.hibernate.orm.test.annotations.id.sequences.entities.BreakDance;
|
||||||
import org.hibernate.orm.test.annotations.id.sequences.entities.Computer;
|
import org.hibernate.orm.test.annotations.id.sequences.entities.Computer;
|
||||||
|
|
|
@ -1130,7 +1130,7 @@ public class DefaultCatalogAndSchemaTest {
|
||||||
public static class EntityWithDefaultQualifiersWithTableGenerator {
|
public static class EntityWithDefaultQualifiersWithTableGenerator {
|
||||||
public static final String NAME = "EntityWithDefaultQualifiersWithTableGenerator";
|
public static final String NAME = "EntityWithDefaultQualifiersWithTableGenerator";
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = NAME + "_generator")
|
@GeneratedValue(strategy = GenerationType.TABLE, generator = NAME + "_generator")
|
||||||
@TableGenerator(name = NAME + "_generator", table = NAME + "_tableseq")
|
@TableGenerator(name = NAME + "_generator", table = NAME + "_tableseq")
|
||||||
private Long id;
|
private Long id;
|
||||||
@Basic
|
@Basic
|
||||||
|
@ -1142,7 +1142,7 @@ public class DefaultCatalogAndSchemaTest {
|
||||||
public static class EntityWithExplicitQualifiersWithTableGenerator {
|
public static class EntityWithExplicitQualifiersWithTableGenerator {
|
||||||
public static final String NAME = "EntityWithExplicitQualifiersWithTableGenerator";
|
public static final String NAME = "EntityWithExplicitQualifiersWithTableGenerator";
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = NAME + "_generator")
|
@GeneratedValue(strategy = GenerationType.TABLE, generator = NAME + "_generator")
|
||||||
@TableGenerator(name = NAME + "_generator", table = NAME + "_tableseq",
|
@TableGenerator(name = NAME + "_generator", table = NAME + "_tableseq",
|
||||||
catalog = EXPLICIT_CATALOG, schema = EXPLICIT_SCHEMA)
|
catalog = EXPLICIT_CATALOG, schema = EXPLICIT_SCHEMA)
|
||||||
private Long id;
|
private Long id;
|
||||||
|
@ -1155,7 +1155,7 @@ public class DefaultCatalogAndSchemaTest {
|
||||||
public static class EntityWithDefaultQualifiersWithIncrementGenerator {
|
public static class EntityWithDefaultQualifiersWithIncrementGenerator {
|
||||||
public static final String NAME = "EntityWithDefaultQualifiersWithIncrementGenerator";
|
public static final String NAME = "EntityWithDefaultQualifiersWithIncrementGenerator";
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = NAME + "_generator")
|
@GeneratedValue(generator = NAME + "_generator")
|
||||||
@GenericGenerator(name = NAME + "_generator", strategy = "increment")
|
@GenericGenerator(name = NAME + "_generator", strategy = "increment")
|
||||||
private Long id;
|
private Long id;
|
||||||
@Basic
|
@Basic
|
||||||
|
@ -1167,7 +1167,7 @@ public class DefaultCatalogAndSchemaTest {
|
||||||
public static class EntityWithExplicitQualifiersWithIncrementGenerator {
|
public static class EntityWithExplicitQualifiersWithIncrementGenerator {
|
||||||
public static final String NAME = "EntityWithExplicitQualifiersWithIncrementGenerator";
|
public static final String NAME = "EntityWithExplicitQualifiersWithIncrementGenerator";
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = NAME + "_generator")
|
@GeneratedValue(generator = NAME + "_generator")
|
||||||
@GenericGenerator(name = NAME + "_generator", strategy = "increment", parameters = {
|
@GenericGenerator(name = NAME + "_generator", strategy = "increment", parameters = {
|
||||||
@Parameter(name = "catalog", value = EXPLICIT_CATALOG),
|
@Parameter(name = "catalog", value = EXPLICIT_CATALOG),
|
||||||
@Parameter(name = "schema", value = EXPLICIT_SCHEMA)
|
@Parameter(name = "schema", value = EXPLICIT_SCHEMA)
|
||||||
|
@ -1181,7 +1181,7 @@ public class DefaultCatalogAndSchemaTest {
|
||||||
public static class EntityWithDefaultQualifiersWithEnhancedSequenceGenerator {
|
public static class EntityWithDefaultQualifiersWithEnhancedSequenceGenerator {
|
||||||
public static final String NAME = "EntityWithDefaultQualifiersWithEnhancedSequenceGenerator";
|
public static final String NAME = "EntityWithDefaultQualifiersWithEnhancedSequenceGenerator";
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = NAME + "_generator")
|
@GeneratedValue(generator = NAME + "_generator")
|
||||||
@GenericGenerator(name = NAME + "_generator", strategy = "enhanced-sequence", parameters = {
|
@GenericGenerator(name = NAME + "_generator", strategy = "enhanced-sequence", parameters = {
|
||||||
@Parameter(name = "sequence_name", value = NAME + "_seq")
|
@Parameter(name = "sequence_name", value = NAME + "_seq")
|
||||||
})
|
})
|
||||||
|
@ -1195,7 +1195,7 @@ public class DefaultCatalogAndSchemaTest {
|
||||||
public static class EntityWithExplicitQualifiersWithEnhancedSequenceGenerator {
|
public static class EntityWithExplicitQualifiersWithEnhancedSequenceGenerator {
|
||||||
public static final String NAME = "EntityWithExplicitQualifiersWithEnhancedSequenceGenerator";
|
public static final String NAME = "EntityWithExplicitQualifiersWithEnhancedSequenceGenerator";
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = NAME + "_generator")
|
@GeneratedValue(generator = NAME + "_generator")
|
||||||
@GenericGenerator(name = NAME + "_generator", strategy = "enhanced-sequence", parameters = {
|
@GenericGenerator(name = NAME + "_generator", strategy = "enhanced-sequence", parameters = {
|
||||||
@Parameter(name = "sequence_name", value = NAME + "_seq"),
|
@Parameter(name = "sequence_name", value = NAME + "_seq"),
|
||||||
@Parameter(name = "catalog", value = EXPLICIT_CATALOG),
|
@Parameter(name = "catalog", value = EXPLICIT_CATALOG),
|
||||||
|
|
|
@ -25,6 +25,7 @@ import org.hibernate.dialect.SybaseDialect;
|
||||||
import org.hibernate.generator.Generator;
|
import org.hibernate.generator.Generator;
|
||||||
import org.hibernate.id.IdentifierGenerator;
|
import org.hibernate.id.IdentifierGenerator;
|
||||||
import org.hibernate.id.UUIDGenerator;
|
import org.hibernate.id.UUIDGenerator;
|
||||||
|
import org.hibernate.id.uuid.UuidGenerator;
|
||||||
import org.hibernate.mapping.KeyValue;
|
import org.hibernate.mapping.KeyValue;
|
||||||
import org.hibernate.mapping.PersistentClass;
|
import org.hibernate.mapping.PersistentClass;
|
||||||
import org.hibernate.mapping.RootClass;
|
import org.hibernate.mapping.RootClass;
|
||||||
|
@ -60,9 +61,8 @@ public class GeneratedValueTest {
|
||||||
assertEquals( UUID.class, entityBinding.getIdentifier().getType().getReturnedClass() );
|
assertEquals( UUID.class, entityBinding.getIdentifier().getType().getReturnedClass() );
|
||||||
KeyValue keyValue = entityBinding.getIdentifier();
|
KeyValue keyValue = entityBinding.getIdentifier();
|
||||||
Dialect dialect = metadata.getDatabase().getDialect();
|
Dialect dialect = metadata.getDatabase().getDialect();
|
||||||
final Generator generator1 = keyValue.createGenerator( dialect, (RootClass) entityBinding);
|
final Generator generator = keyValue.createGenerator( dialect, (RootClass) entityBinding);
|
||||||
IdentifierGenerator generator = generator1 instanceof IdentifierGenerator ? (IdentifierGenerator) generator1 : null;
|
assertTyping( UuidGenerator.class, generator );
|
||||||
assertTyping( UUIDGenerator.class, generator );
|
|
||||||
|
|
||||||
// now a functional test
|
// now a functional test
|
||||||
SessionFactory sf = metadata.buildSessionFactory();
|
SessionFactory sf = metadata.buildSessionFactory();
|
||||||
|
|
|
@ -15,6 +15,8 @@ import jakarta.persistence.JoinColumn;
|
||||||
import jakarta.persistence.ManyToOne;
|
import jakarta.persistence.ManyToOne;
|
||||||
import jakarta.persistence.OneToMany;
|
import jakarta.persistence.OneToMany;
|
||||||
import jakarta.persistence.Table;
|
import jakarta.persistence.Table;
|
||||||
|
import org.hamcrest.MatcherAssert;
|
||||||
|
|
||||||
import org.hibernate.annotations.CollectionId;
|
import org.hibernate.annotations.CollectionId;
|
||||||
import org.hibernate.annotations.CollectionIdJdbcTypeCode;
|
import org.hibernate.annotations.CollectionIdJdbcTypeCode;
|
||||||
import org.hibernate.boot.Metadata;
|
import org.hibernate.boot.Metadata;
|
||||||
|
@ -28,6 +30,7 @@ import org.hibernate.id.IncrementGenerator;
|
||||||
import org.hibernate.id.UUIDGenerator;
|
import org.hibernate.id.UUIDGenerator;
|
||||||
import org.hibernate.id.enhanced.DatabaseStructure;
|
import org.hibernate.id.enhanced.DatabaseStructure;
|
||||||
import org.hibernate.id.enhanced.SequenceStyleGenerator;
|
import org.hibernate.id.enhanced.SequenceStyleGenerator;
|
||||||
|
import org.hibernate.id.uuid.UuidGenerator;
|
||||||
import org.hibernate.mapping.IdentifierBag;
|
import org.hibernate.mapping.IdentifierBag;
|
||||||
import org.hibernate.mapping.KeyValue;
|
import org.hibernate.mapping.KeyValue;
|
||||||
import org.hibernate.mapping.PersistentClass;
|
import org.hibernate.mapping.PersistentClass;
|
||||||
|
@ -131,12 +134,11 @@ public class AutoGenerationTypeTests {
|
||||||
.buildMetadata();
|
.buildMetadata();
|
||||||
|
|
||||||
final PersistentClass entityBinding = metadata.getEntityBinding( Entity4.class.getName() );
|
final PersistentClass entityBinding = metadata.getEntityBinding( Entity4.class.getName() );
|
||||||
|
final Property identifierProperty = entityBinding.getRootClass().getIdentifierProperty();
|
||||||
final KeyValue idMapping = entityBinding.getRootClass().getIdentifier();
|
final KeyValue idMapping = entityBinding.getRootClass().getIdentifier();
|
||||||
Dialect dialect = new H2Dialect();
|
Dialect dialect = new H2Dialect();
|
||||||
final Generator generator = idMapping.createGenerator( dialect, entityBinding.getRootClass());
|
final Generator generator = idMapping.createGenerator( dialect, entityBinding.getRootClass(), identifierProperty );
|
||||||
final IdentifierGenerator idGenerator = generator instanceof IdentifierGenerator ? (IdentifierGenerator) generator : null;
|
MatcherAssert.assertThat( generator, instanceOf( UuidGenerator.class ) );
|
||||||
|
|
||||||
assertThat( idGenerator, instanceOf( UUIDGenerator.class ) );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -131,7 +131,7 @@ public class HiLoSequenceMismatchStrategyTest {
|
||||||
public static class TestEntity {
|
public static class TestEntity {
|
||||||
|
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "hilo_sequence_generator")
|
@GeneratedValue(generator = "hilo_sequence_generator")
|
||||||
@GenericGenerator(name = "hilo_sequence_generator", strategy = "org.hibernate.id.enhanced.SequenceStyleGenerator", parameters = {
|
@GenericGenerator(name = "hilo_sequence_generator", strategy = "org.hibernate.id.enhanced.SequenceStyleGenerator", parameters = {
|
||||||
@Parameter(name = "sequence_name", value = sequenceName),
|
@Parameter(name = "sequence_name", value = sequenceName),
|
||||||
@Parameter(name = "initial_value", value = "1"),
|
@Parameter(name = "initial_value", value = "1"),
|
||||||
|
|
|
@ -26,7 +26,6 @@ public class ImplicitUuidGenerationTests {
|
||||||
@Test
|
@Test
|
||||||
@ServiceRegistry
|
@ServiceRegistry
|
||||||
@DomainModel(annotatedClasses = Book.class)
|
@DomainModel(annotatedClasses = Book.class)
|
||||||
@FailureExpected( jiraKey = "HHH-18420", reason = "Implicit UUID generation continues to use UUIDGenerator for the time being" )
|
|
||||||
void verifyModel(ServiceRegistryScope registryScope, DomainModelScope domainModelScope) {
|
void verifyModel(ServiceRegistryScope registryScope, DomainModelScope domainModelScope) {
|
||||||
domainModelScope.withHierarchy( Book.class, (descriptor) -> {
|
domainModelScope.withHierarchy( Book.class, (descriptor) -> {
|
||||||
Helper.verifyAlgorithm( registryScope, domainModelScope, descriptor, StandardRandomStrategy.class );
|
Helper.verifyAlgorithm( registryScope, domainModelScope, descriptor, StandardRandomStrategy.class );
|
||||||
|
|
|
@ -11,7 +11,6 @@ import org.hibernate.orm.test.mapping.identifier.uuid.Helper;
|
||||||
|
|
||||||
import org.hibernate.testing.orm.junit.DomainModel;
|
import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
import org.hibernate.testing.orm.junit.DomainModelScope;
|
import org.hibernate.testing.orm.junit.DomainModelScope;
|
||||||
import org.hibernate.testing.orm.junit.FailureExpected;
|
|
||||||
import org.hibernate.testing.orm.junit.ServiceRegistry;
|
import org.hibernate.testing.orm.junit.ServiceRegistry;
|
||||||
import org.hibernate.testing.orm.junit.ServiceRegistryScope;
|
import org.hibernate.testing.orm.junit.ServiceRegistryScope;
|
||||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||||
|
@ -26,7 +25,6 @@ public class Implicit2UuidGenerationTests {
|
||||||
@Test
|
@Test
|
||||||
@ServiceRegistry
|
@ServiceRegistry
|
||||||
@DomainModel(annotatedClasses = Book.class)
|
@DomainModel(annotatedClasses = Book.class)
|
||||||
@FailureExpected( jiraKey = "HHH-18420", reason = "Implicit UUID generation continues to use UUIDGenerator for the time being" )
|
|
||||||
void verifyModel(ServiceRegistryScope registryScope, DomainModelScope domainModelScope) {
|
void verifyModel(ServiceRegistryScope registryScope, DomainModelScope domainModelScope) {
|
||||||
domainModelScope.withHierarchy( Book.class, (descriptor) -> {
|
domainModelScope.withHierarchy( Book.class, (descriptor) -> {
|
||||||
Helper.verifyAlgorithm( registryScope, domainModelScope, descriptor, StandardRandomStrategy.class );
|
Helper.verifyAlgorithm( registryScope, domainModelScope, descriptor, StandardRandomStrategy.class );
|
||||||
|
|
|
@ -26,7 +26,6 @@ public class Implicit3UuidGenerationTests {
|
||||||
@Test
|
@Test
|
||||||
@ServiceRegistry
|
@ServiceRegistry
|
||||||
@DomainModel(annotatedClasses = Book.class)
|
@DomainModel(annotatedClasses = Book.class)
|
||||||
@FailureExpected( jiraKey = "HHH-18420", reason = "Implicit UUID generation continues to use UUIDGenerator for the time being" )
|
|
||||||
void verifyModel(ServiceRegistryScope registryScope, DomainModelScope domainModelScope) {
|
void verifyModel(ServiceRegistryScope registryScope, DomainModelScope domainModelScope) {
|
||||||
domainModelScope.withHierarchy( Book.class, (descriptor) -> {
|
domainModelScope.withHierarchy( Book.class, (descriptor) -> {
|
||||||
Helper.verifyAlgorithm( registryScope, domainModelScope, descriptor, StandardRandomStrategy.class );
|
Helper.verifyAlgorithm( registryScope, domainModelScope, descriptor, StandardRandomStrategy.class );
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
rootProject.name = 'local-build-plugins'
|
|
Loading…
Reference in New Issue