HHH-18620 - Add @NativeGenerator
This commit is contained in:
parent
fccbb8d582
commit
df405d37ab
|
@ -51,6 +51,7 @@ import org.hibernate.type.StandardBasicTypes;
|
||||||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||||
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
|
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
|
||||||
|
|
||||||
|
import jakarta.persistence.GenerationType;
|
||||||
import jakarta.persistence.TemporalType;
|
import jakarta.persistence.TemporalType;
|
||||||
|
|
||||||
import static org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtractor.extractUsingTemplate;
|
import static org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtractor.extractUsingTemplate;
|
||||||
|
@ -283,10 +284,9 @@ public class CacheDialect extends Dialect {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getNativeIdentifierGeneratorStrategy() {
|
public GenerationType getNativeValueGenerationStrategy() {
|
||||||
return "identity";
|
return GenerationType.IDENTITY;
|
||||||
}
|
}
|
||||||
|
|
||||||
// IDENTITY support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// IDENTITY support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
|
@ -75,6 +75,7 @@ import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
|
import jakarta.persistence.GenerationType;
|
||||||
import jakarta.persistence.TemporalType;
|
import jakarta.persistence.TemporalType;
|
||||||
|
|
||||||
import static org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtractor.extractUsingTemplate;
|
import static org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtractor.extractUsingTemplate;
|
||||||
|
@ -654,8 +655,8 @@ public class CockroachLegacyDialect extends Dialect {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getNativeIdentifierGeneratorStrategy() {
|
public GenerationType getNativeValueGenerationStrategy() {
|
||||||
return "sequence";
|
return GenerationType.SEQUENCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -100,6 +100,7 @@ import org.hibernate.type.descriptor.sql.internal.DdlTypeImpl;
|
||||||
import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry;
|
import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry;
|
||||||
import org.hibernate.type.spi.TypeConfiguration;
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
|
import jakarta.persistence.GenerationType;
|
||||||
import jakarta.persistence.TemporalType;
|
import jakarta.persistence.TemporalType;
|
||||||
|
|
||||||
import static java.util.regex.Pattern.CASE_INSENSITIVE;
|
import static java.util.regex.Pattern.CASE_INSENSITIVE;
|
||||||
|
@ -962,8 +963,8 @@ public class OracleLegacyDialect extends Dialect {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getNativeIdentifierGeneratorStrategy() {
|
public GenerationType getNativeValueGenerationStrategy() {
|
||||||
return "sequence";
|
return GenerationType.SEQUENCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// features which change between 8i, 9i, and 10g ~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// features which change between 8i, 9i, and 10g ~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
|
@ -93,6 +93,7 @@ import org.hibernate.type.descriptor.sql.internal.Scale6IntervalSecondDdlType;
|
||||||
import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry;
|
import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry;
|
||||||
import org.hibernate.type.spi.TypeConfiguration;
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
|
import jakarta.persistence.GenerationType;
|
||||||
import jakarta.persistence.TemporalType;
|
import jakarta.persistence.TemporalType;
|
||||||
|
|
||||||
import static org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtractor.extractUsingTemplate;
|
import static org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtractor.extractUsingTemplate;
|
||||||
|
@ -894,8 +895,8 @@ public class PostgreSQLLegacyDialect extends Dialect {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getNativeIdentifierGeneratorStrategy() {
|
public GenerationType getNativeValueGenerationStrategy() {
|
||||||
return "sequence";
|
return GenerationType.SEQUENCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
* Copyright Red Hat Inc. and Hibernate Authors
|
||||||
|
*/
|
||||||
|
package org.hibernate.annotations;
|
||||||
|
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
|
||||||
|
import org.hibernate.Incubating;
|
||||||
|
import org.hibernate.dialect.Dialect;
|
||||||
|
|
||||||
|
import jakarta.persistence.SequenceGenerator;
|
||||||
|
import jakarta.persistence.TableGenerator;
|
||||||
|
|
||||||
|
import static java.lang.annotation.ElementType.FIELD;
|
||||||
|
import static java.lang.annotation.ElementType.METHOD;
|
||||||
|
import static java.lang.annotation.ElementType.PACKAGE;
|
||||||
|
import static java.lang.annotation.ElementType.TYPE;
|
||||||
|
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generator that picks a strategy based on the {@linkplain Dialect#getNativeValueGenerationStrategy() dialect}.
|
||||||
|
*
|
||||||
|
* @since 7.0
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
@Target({METHOD, FIELD, TYPE, PACKAGE})
|
||||||
|
@Retention(RUNTIME)
|
||||||
|
@IdGeneratorType(org.hibernate.id.NativeGenerator.class)
|
||||||
|
@Incubating
|
||||||
|
public @interface NativeGenerator {
|
||||||
|
SequenceGenerator sequenceForm() default @SequenceGenerator();
|
||||||
|
TableGenerator tableForm() default @TableGenerator();
|
||||||
|
}
|
|
@ -0,0 +1,198 @@
|
||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
* Copyright Red Hat Inc. and Hibernate Authors
|
||||||
|
*/
|
||||||
|
package org.hibernate.boot.model.internal;
|
||||||
|
|
||||||
|
import java.lang.annotation.Annotation;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.hibernate.MappingException;
|
||||||
|
import org.hibernate.annotations.IdGeneratorType;
|
||||||
|
import org.hibernate.boot.model.IdentifierGeneratorDefinition;
|
||||||
|
import org.hibernate.boot.model.relational.Database;
|
||||||
|
import org.hibernate.boot.spi.MetadataBuildingContext;
|
||||||
|
import org.hibernate.dialect.Dialect;
|
||||||
|
import org.hibernate.generator.Generator;
|
||||||
|
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||||
|
import org.hibernate.mapping.Column;
|
||||||
|
import org.hibernate.mapping.PersistentClass;
|
||||||
|
import org.hibernate.mapping.SimpleValue;
|
||||||
|
import org.hibernate.models.spi.AnnotationTarget;
|
||||||
|
import org.hibernate.models.spi.ClassDetails;
|
||||||
|
import org.hibernate.models.spi.MemberDetails;
|
||||||
|
|
||||||
|
import jakarta.persistence.GeneratedValue;
|
||||||
|
|
||||||
|
import static org.hibernate.boot.model.internal.GeneratorAnnotationHelper.handleIdGeneratorType;
|
||||||
|
import static org.hibernate.boot.model.internal.GeneratorParameters.identityTablesString;
|
||||||
|
import static org.hibernate.boot.model.internal.GeneratorStrategies.mapLegacyNamedGenerator;
|
||||||
|
import static org.hibernate.id.IdentifierGenerator.ENTITY_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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Template support for IdGeneratorResolver implementations dealing with entity identifiers
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public abstract class AbstractEntityIdGeneratorResolver implements IdGeneratorResolver {
|
||||||
|
protected final PersistentClass entityMapping;
|
||||||
|
protected final SimpleValue idValue;
|
||||||
|
protected final MemberDetails idMember;
|
||||||
|
protected final GeneratedValue generatedValue;
|
||||||
|
protected final MetadataBuildingContext buildingContext;
|
||||||
|
|
||||||
|
public AbstractEntityIdGeneratorResolver(
|
||||||
|
PersistentClass entityMapping,
|
||||||
|
SimpleValue idValue,
|
||||||
|
MemberDetails idMember,
|
||||||
|
GeneratedValue generatedValue,
|
||||||
|
MetadataBuildingContext buildingContext) {
|
||||||
|
this.entityMapping = entityMapping;
|
||||||
|
this.idValue = idValue;
|
||||||
|
this.idMember = idMember;
|
||||||
|
this.generatedValue = generatedValue;
|
||||||
|
this.buildingContext = buildingContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final void doSecondPass(Map<String, PersistentClass> persistentClasses) throws MappingException {
|
||||||
|
switch ( generatedValue.strategy() ) {
|
||||||
|
case UUID -> GeneratorAnnotationHelper.handleUuidStrategy( idValue, idMember, buildingContext );
|
||||||
|
case IDENTITY -> GeneratorAnnotationHelper.handleIdentityStrategy( idValue );
|
||||||
|
case SEQUENCE -> handleSequenceStrategy();
|
||||||
|
case TABLE -> handleTableStrategy();
|
||||||
|
case AUTO -> handleAutoStrategy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleSequenceStrategy() {
|
||||||
|
if ( generatedValue.generator().isEmpty() ) {
|
||||||
|
handleUnnamedSequenceGenerator();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
handleNamedSequenceGenerator();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void handleUnnamedSequenceGenerator();
|
||||||
|
|
||||||
|
protected abstract void handleNamedSequenceGenerator();
|
||||||
|
|
||||||
|
private void handleTableStrategy() {
|
||||||
|
if ( generatedValue.generator().isEmpty() ) {
|
||||||
|
handleUnnamedTableGenerator();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
handleNamedTableGenerator();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void handleUnnamedTableGenerator();
|
||||||
|
|
||||||
|
protected abstract void handleNamedTableGenerator();
|
||||||
|
|
||||||
|
private void handleAutoStrategy() {
|
||||||
|
if ( generatedValue.generator().isEmpty() ) {
|
||||||
|
handleUnnamedAutoGenerator();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
handleNamedAutoGenerator();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void handleUnnamedAutoGenerator();
|
||||||
|
|
||||||
|
protected abstract void handleNamedAutoGenerator();
|
||||||
|
|
||||||
|
protected boolean handleAsMetaAnnotated() {
|
||||||
|
final Annotation fromMember = findGeneratorAnnotation( idMember );
|
||||||
|
if ( fromMember != null ) {
|
||||||
|
handleIdGeneratorType( fromMember, idValue, idMember, buildingContext );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Annotation fromClass = findGeneratorAnnotation( idMember.getDeclaringType() );
|
||||||
|
if ( fromClass != null ) {
|
||||||
|
handleIdGeneratorType( fromClass, idValue, idMember, buildingContext );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
final ClassDetails packageInfoDetails = GeneratorAnnotationHelper.locatePackageInfoDetails( idMember.getDeclaringType(), buildingContext );
|
||||||
|
if ( packageInfoDetails != null ) {
|
||||||
|
final Annotation fromPackage = findGeneratorAnnotation( packageInfoDetails );
|
||||||
|
if ( fromPackage != null ) {
|
||||||
|
handleIdGeneratorType( fromPackage, idValue, idMember, buildingContext );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Annotation findGeneratorAnnotation(AnnotationTarget annotationTarget) {
|
||||||
|
final List<? extends Annotation> metaAnnotated = annotationTarget.getMetaAnnotated( IdGeneratorType.class, buildingContext.getMetadataCollector().getSourceModelBuildingContext() );
|
||||||
|
if ( CollectionHelper.size( metaAnnotated ) > 0 ) {
|
||||||
|
return metaAnnotated.get( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean handleAsLegacyGenerator() {
|
||||||
|
// Handle a few legacy Hibernate generators...
|
||||||
|
final String nameFromGeneratedValue = generatedValue.generator();
|
||||||
|
if ( !nameFromGeneratedValue.isEmpty() ) {
|
||||||
|
final Class<? extends Generator> legacyNamedGenerator = mapLegacyNamedGenerator( nameFromGeneratedValue, idValue );
|
||||||
|
if ( legacyNamedGenerator != null ) {
|
||||||
|
final Map<String,String> configuration = buildLegacyGeneratorConfig();
|
||||||
|
//noinspection unchecked,rawtypes
|
||||||
|
GeneratorBinder.createGeneratorFrom(
|
||||||
|
new IdentifierGeneratorDefinition( nameFromGeneratedValue, legacyNamedGenerator.getName(), configuration ),
|
||||||
|
idValue,
|
||||||
|
(Map) configuration,
|
||||||
|
buildingContext
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,33 +8,46 @@ import java.lang.annotation.Annotation;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.Properties;
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
import org.hibernate.annotations.GenericGenerator;
|
import org.hibernate.annotations.GenericGenerator;
|
||||||
|
import org.hibernate.annotations.IdGeneratorType;
|
||||||
import org.hibernate.annotations.Parameter;
|
import org.hibernate.annotations.Parameter;
|
||||||
import org.hibernate.boot.model.IdentifierGeneratorDefinition;
|
import org.hibernate.boot.model.IdentifierGeneratorDefinition;
|
||||||
|
import org.hibernate.boot.model.relational.ExportableProducer;
|
||||||
import org.hibernate.boot.models.HibernateAnnotations;
|
import org.hibernate.boot.models.HibernateAnnotations;
|
||||||
import org.hibernate.boot.registry.classloading.spi.ClassLoadingException;
|
import org.hibernate.boot.registry.classloading.spi.ClassLoadingException;
|
||||||
import org.hibernate.boot.spi.MetadataBuildingContext;
|
import org.hibernate.boot.spi.MetadataBuildingContext;
|
||||||
|
import org.hibernate.generator.AnnotationBasedGenerator;
|
||||||
import org.hibernate.generator.Generator;
|
import org.hibernate.generator.Generator;
|
||||||
|
import org.hibernate.generator.GeneratorCreationContext;
|
||||||
|
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.UuidGenerator;
|
import org.hibernate.id.uuid.UuidGenerator;
|
||||||
import org.hibernate.internal.util.StringHelper;
|
import org.hibernate.internal.util.StringHelper;
|
||||||
import org.hibernate.mapping.PersistentClass;
|
import org.hibernate.mapping.PersistentClass;
|
||||||
import org.hibernate.mapping.RootClass;
|
|
||||||
import org.hibernate.mapping.SimpleValue;
|
import org.hibernate.mapping.SimpleValue;
|
||||||
import org.hibernate.models.spi.AnnotationDescriptor;
|
import org.hibernate.models.spi.AnnotationDescriptor;
|
||||||
import org.hibernate.models.spi.ClassDetails;
|
import org.hibernate.models.spi.ClassDetails;
|
||||||
|
import org.hibernate.models.spi.ClassDetailsRegistry;
|
||||||
import org.hibernate.models.spi.MemberDetails;
|
import org.hibernate.models.spi.MemberDetails;
|
||||||
import org.hibernate.models.spi.SourceModelBuildingContext;
|
import org.hibernate.models.spi.SourceModelBuildingContext;
|
||||||
|
import org.hibernate.models.spi.SourceModelContext;
|
||||||
|
import org.hibernate.resource.beans.container.spi.BeanContainer;
|
||||||
|
|
||||||
import jakarta.persistence.SequenceGenerator;
|
import jakarta.persistence.SequenceGenerator;
|
||||||
import jakarta.persistence.TableGenerator;
|
import jakarta.persistence.TableGenerator;
|
||||||
|
|
||||||
|
import static org.hibernate.boot.model.internal.GeneratorParameters.collectBaselineProperties;
|
||||||
|
import static org.hibernate.boot.model.internal.GeneratorParameters.fallbackAllocationSize;
|
||||||
import static org.hibernate.id.IdentifierGenerator.GENERATOR_NAME;
|
import static org.hibernate.id.IdentifierGenerator.GENERATOR_NAME;
|
||||||
|
import static org.hibernate.id.OptimizableGenerator.INCREMENT_PARAM;
|
||||||
import static org.hibernate.internal.util.config.ConfigurationHelper.setIfNotEmpty;
|
import static org.hibernate.internal.util.config.ConfigurationHelper.setIfNotEmpty;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -92,13 +105,9 @@ public class GeneratorAnnotationHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
// lastly, on the package
|
// lastly, on the package
|
||||||
final String packageInfoFqn = StringHelper.qualifier( idMember.getDeclaringType().getClassName() ) + ".package-info";
|
final ClassDetails packageInfo = locatePackageInfoDetails( idMember.getDeclaringType(), context );
|
||||||
try {
|
if ( packageInfo !=
|
||||||
final ClassDetails packageInfo =
|
null ) {
|
||||||
context.getMetadataCollector()
|
|
||||||
.getSourceModelBuildingContext()
|
|
||||||
.getClassDetailsRegistry()
|
|
||||||
.resolveClassDetails( packageInfoFqn );
|
|
||||||
for ( A generatorAnnotation : packageInfo.getRepeatedAnnotationUsages( generatorAnnotationType, sourceModelContext ) ) {
|
for ( A generatorAnnotation : packageInfo.getRepeatedAnnotationUsages( generatorAnnotationType, sourceModelContext ) ) {
|
||||||
if ( nameExtractor != null ) {
|
if ( nameExtractor != null ) {
|
||||||
final String registrationName = nameExtractor.apply( generatorAnnotation );
|
final String registrationName = nameExtractor.apply( generatorAnnotation );
|
||||||
|
@ -118,13 +127,178 @@ public class GeneratorAnnotationHelper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (ClassLoadingException e) {
|
|
||||||
// means there is no package-info
|
|
||||||
}
|
|
||||||
|
|
||||||
return possibleMatch;
|
return possibleMatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static ClassDetails locatePackageInfoDetails(ClassDetails classDetails, MetadataBuildingContext buildingContext) {
|
||||||
|
return locatePackageInfoDetails( classDetails, buildingContext.getMetadataCollector().getSourceModelBuildingContext() );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ClassDetails locatePackageInfoDetails(ClassDetails classDetails, SourceModelContext modelContext) {
|
||||||
|
return locatePackageInfoDetails( classDetails, modelContext.getClassDetailsRegistry() );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ClassDetails locatePackageInfoDetails(ClassDetails classDetails, ClassDetailsRegistry classDetailsRegistry) {
|
||||||
|
final String packageInfoFqn = StringHelper.qualifier( classDetails.getName() ) + ".package-info";
|
||||||
|
try {
|
||||||
|
return classDetailsRegistry.resolveClassDetails( packageInfoFqn );
|
||||||
|
}
|
||||||
|
catch (ClassLoadingException e) {
|
||||||
|
// means there is no package-info
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void handleSequenceGenerator(
|
||||||
|
String nameFromGeneratedValue,
|
||||||
|
SequenceGenerator generatorAnnotation,
|
||||||
|
SimpleValue idValue,
|
||||||
|
MemberDetails idMember,
|
||||||
|
MetadataBuildingContext buildingContext) {
|
||||||
|
idValue.setCustomIdGeneratorCreator( (creationContext) -> {
|
||||||
|
final BeanContainer beanContainer = GeneratorBinder.beanContainer( buildingContext );
|
||||||
|
final SequenceStyleGenerator identifierGenerator = GeneratorBinder.instantiateGenerator(
|
||||||
|
beanContainer,
|
||||||
|
SequenceStyleGenerator.class
|
||||||
|
);
|
||||||
|
prepareForUse(
|
||||||
|
identifierGenerator,
|
||||||
|
generatorAnnotation,
|
||||||
|
idMember,
|
||||||
|
properties -> {
|
||||||
|
if ( generatorAnnotation != null ) {
|
||||||
|
properties.put( GENERATOR_NAME, generatorAnnotation.name() );
|
||||||
|
}
|
||||||
|
else if ( nameFromGeneratedValue != null ) {
|
||||||
|
properties.put( GENERATOR_NAME, nameFromGeneratedValue );
|
||||||
|
}
|
||||||
|
// we need to better handle default allocation-size here...
|
||||||
|
properties.put( INCREMENT_PARAM, fallbackAllocationSize( generatorAnnotation, buildingContext ) );
|
||||||
|
},
|
||||||
|
generatorAnnotation == null
|
||||||
|
? null
|
||||||
|
: (a, properties) -> SequenceStyleGenerator.applyConfiguration( generatorAnnotation, properties::put ),
|
||||||
|
creationContext
|
||||||
|
);
|
||||||
|
return identifierGenerator;
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void handleTableGenerator(
|
||||||
|
String nameFromGeneratedValue,
|
||||||
|
TableGenerator generatorAnnotation,
|
||||||
|
PersistentClass entityMapping,
|
||||||
|
SimpleValue idValue,
|
||||||
|
MemberDetails idMember,
|
||||||
|
MetadataBuildingContext buildingContext) {
|
||||||
|
idValue.setCustomIdGeneratorCreator( (creationContext) -> {
|
||||||
|
final BeanContainer beanContainer = GeneratorBinder.beanContainer( buildingContext );
|
||||||
|
final org.hibernate.id.enhanced.TableGenerator identifierGenerator = GeneratorBinder.instantiateGenerator(
|
||||||
|
beanContainer,
|
||||||
|
org.hibernate.id.enhanced.TableGenerator.class
|
||||||
|
);
|
||||||
|
GeneratorAnnotationHelper.prepareForUse(
|
||||||
|
identifierGenerator,
|
||||||
|
generatorAnnotation,
|
||||||
|
idMember,
|
||||||
|
properties -> {
|
||||||
|
if ( generatorAnnotation != null ) {
|
||||||
|
properties.put( GENERATOR_NAME, generatorAnnotation.name() );
|
||||||
|
}
|
||||||
|
else if ( nameFromGeneratedValue != null ) {
|
||||||
|
properties.put( GENERATOR_NAME, nameFromGeneratedValue );
|
||||||
|
}
|
||||||
|
// we need to better handle default allocation-size here...
|
||||||
|
properties.put(
|
||||||
|
INCREMENT_PARAM,
|
||||||
|
fallbackAllocationSize( generatorAnnotation, buildingContext )
|
||||||
|
);
|
||||||
|
},
|
||||||
|
generatorAnnotation == null
|
||||||
|
? null
|
||||||
|
: (a, properties) -> org.hibernate.id.enhanced.TableGenerator.applyConfiguration(
|
||||||
|
generatorAnnotation,
|
||||||
|
properties::put
|
||||||
|
),
|
||||||
|
creationContext
|
||||||
|
);
|
||||||
|
return identifierGenerator;
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void handleIdGeneratorType(
|
||||||
|
Annotation generatorAnnotation,
|
||||||
|
SimpleValue idValue,
|
||||||
|
MemberDetails idMember,
|
||||||
|
MetadataBuildingContext buildingContext) {
|
||||||
|
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()
|
||||||
|
);
|
||||||
|
GeneratorAnnotationHelper.prepareForUse(
|
||||||
|
identifierGenerator,
|
||||||
|
generatorAnnotation,
|
||||||
|
idMember,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
creationContext
|
||||||
|
);
|
||||||
|
return identifierGenerator;
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepares a generator for use by handling its various potential means of "configuration".
|
||||||
|
*
|
||||||
|
* @param generator The "empty" generator
|
||||||
|
* @param annotation The annotation which defines configuration for the generator
|
||||||
|
* @param idMember The member defining the id
|
||||||
|
* @param configBaseline Allows to set any default values. Called before common config is handled.
|
||||||
|
* @param configExtractor Allows to extract values from the generator annotation. Called after common config is handled.
|
||||||
|
* @param creationContext Access to useful information
|
||||||
|
*/
|
||||||
|
public static <A extends Annotation> void prepareForUse(
|
||||||
|
Generator generator,
|
||||||
|
A annotation,
|
||||||
|
MemberDetails idMember,
|
||||||
|
Consumer<Properties> configBaseline,
|
||||||
|
BiConsumer<A,Properties> configExtractor,
|
||||||
|
GeneratorCreationContext creationContext) {
|
||||||
|
if ( generator instanceof AnnotationBasedGenerator ) {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
final AnnotationBasedGenerator<A> generation = (AnnotationBasedGenerator<A>) generator;
|
||||||
|
generation.initialize( annotation, idMember.toJavaMember(), creationContext );
|
||||||
|
}
|
||||||
|
if ( generator instanceof Configurable configurable ) {
|
||||||
|
final Properties properties = new Properties();
|
||||||
|
if ( configBaseline != null ) {
|
||||||
|
configBaseline.accept( properties );
|
||||||
|
}
|
||||||
|
collectBaselineProperties(
|
||||||
|
creationContext.getProperty() != null
|
||||||
|
? (SimpleValue) creationContext.getProperty().getValue()
|
||||||
|
: (SimpleValue) creationContext.getPersistentClass().getIdentifierProperty().getValue(),
|
||||||
|
creationContext.getDatabase().getDialect(),
|
||||||
|
creationContext.getRootClass(),
|
||||||
|
properties::setProperty
|
||||||
|
);
|
||||||
|
if ( configExtractor != null ) {
|
||||||
|
configExtractor.accept( annotation, properties );
|
||||||
|
}
|
||||||
|
configurable.configure( creationContext, properties );
|
||||||
|
}
|
||||||
|
if ( generator instanceof ExportableProducer exportableProducer ) {
|
||||||
|
exportableProducer.registerExportables( creationContext.getDatabase() );
|
||||||
|
}
|
||||||
|
if ( generator instanceof Configurable configurable ) {
|
||||||
|
configurable.initialize( creationContext.getSqlStringGenerationContext() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void handleUuidStrategy(
|
public static void handleUuidStrategy(
|
||||||
SimpleValue idValue,
|
SimpleValue idValue,
|
||||||
MemberDetails idMember,
|
MemberDetails idMember,
|
||||||
|
@ -144,44 +318,6 @@ public class GeneratorAnnotationHelper {
|
||||||
idValue.setColumnToIdentity();
|
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(
|
public static void handleGenericGenerator(
|
||||||
String generatorName,
|
String generatorName,
|
||||||
GenericGenerator generatorConfig,
|
GenericGenerator generatorConfig,
|
||||||
|
@ -221,22 +357,4 @@ public class GeneratorAnnotationHelper {
|
||||||
configuration.put( parameter.name(), parameter.value() );
|
configuration.put( parameter.name(), parameter.value() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void handleTableGenerator(
|
|
||||||
String generatorName,
|
|
||||||
TableGenerator generatorConfig,
|
|
||||||
PersistentClass entityMapping,
|
|
||||||
SimpleValue idValue,
|
|
||||||
MetadataBuildingContext context) {
|
|
||||||
final Map<String,String> configuration = new HashMap<>();
|
|
||||||
applyBaselineConfiguration( generatorConfig, idValue, entityMapping.getRootClass(), context, configuration::put );
|
|
||||||
org.hibernate.id.enhanced.TableGenerator.applyConfiguration( generatorConfig, configuration::put );
|
|
||||||
|
|
||||||
GeneratorBinder.createGeneratorFrom(
|
|
||||||
new IdentifierGeneratorDefinition( generatorName, org.hibernate.id.enhanced.TableGenerator.class.getName(), configuration ),
|
|
||||||
idValue,
|
|
||||||
context
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -536,9 +536,9 @@ 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 instantiateGeneratorAsBean(
|
private static <T extends Generator> T instantiateGeneratorAsBean(
|
||||||
BeanContainer beanContainer,
|
BeanContainer beanContainer,
|
||||||
Class<? extends Generator> generatorClass) {
|
Class<T> generatorClass) {
|
||||||
return beanContainer.getBean( generatorClass,
|
return beanContainer.getBean( generatorClass,
|
||||||
new BeanContainer.LifecycleOptions() {
|
new BeanContainer.LifecycleOptions() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -611,9 +611,9 @@ 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}
|
||||||
*/
|
*/
|
||||||
public static Generator instantiateGenerator(
|
public static <T extends Generator> T instantiateGenerator(
|
||||||
BeanContainer beanContainer,
|
BeanContainer beanContainer,
|
||||||
Class<? extends Generator> generatorClass) {
|
Class<T> generatorClass) {
|
||||||
if ( beanContainer != null ) {
|
if ( beanContainer != null ) {
|
||||||
return instantiateGeneratorAsBean( beanContainer, generatorClass );
|
return instantiateGeneratorAsBean( beanContainer, generatorClass );
|
||||||
}
|
}
|
||||||
|
@ -637,7 +637,7 @@ public class GeneratorBinder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static <A extends Annotation> void callInitialize(
|
public static <A extends Annotation> void callInitialize(
|
||||||
A annotation,
|
A annotation,
|
||||||
MemberDetails memberDetails,
|
MemberDetails memberDetails,
|
||||||
GeneratorCreationContext creationContext,
|
GeneratorCreationContext creationContext,
|
||||||
|
@ -725,6 +725,7 @@ public class GeneratorBinder {
|
||||||
persistentClass,
|
persistentClass,
|
||||||
idValue,
|
idValue,
|
||||||
idMember,
|
idMember,
|
||||||
|
generatedValue,
|
||||||
context
|
context
|
||||||
) );
|
) );
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,12 +4,14 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.boot.model.internal;
|
package org.hibernate.boot.model.internal;
|
||||||
|
|
||||||
import jakarta.persistence.SequenceGenerator;
|
import java.lang.annotation.Annotation;
|
||||||
import jakarta.persistence.TableGenerator;
|
import java.util.Map;
|
||||||
import jakarta.persistence.UniqueConstraint;
|
import java.util.Properties;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
|
||||||
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.MetadataImplementor;
|
import org.hibernate.boot.spi.MetadataBuildingContext;
|
||||||
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;
|
||||||
|
@ -30,10 +32,11 @@ import org.hibernate.mapping.RootClass;
|
||||||
import org.hibernate.mapping.SimpleValue;
|
import org.hibernate.mapping.SimpleValue;
|
||||||
import org.hibernate.mapping.Table;
|
import org.hibernate.mapping.Table;
|
||||||
|
|
||||||
import java.util.Map;
|
import jakarta.persistence.SequenceGenerator;
|
||||||
import java.util.Properties;
|
import jakarta.persistence.TableGenerator;
|
||||||
import java.util.function.BiConsumer;
|
import jakarta.persistence.UniqueConstraint;
|
||||||
|
|
||||||
|
import static org.hibernate.cfg.MappingSettings.ID_DB_STRUCTURE_NAMING_STRATEGY;
|
||||||
import static org.hibernate.id.IdentifierGenerator.CONTRIBUTOR_NAME;
|
import static org.hibernate.id.IdentifierGenerator.CONTRIBUTOR_NAME;
|
||||||
import static org.hibernate.id.IdentifierGenerator.ENTITY_NAME;
|
import static org.hibernate.id.IdentifierGenerator.ENTITY_NAME;
|
||||||
import static org.hibernate.id.IdentifierGenerator.JPA_ENTITY_NAME;
|
import static org.hibernate.id.IdentifierGenerator.JPA_ENTITY_NAME;
|
||||||
|
@ -93,15 +96,49 @@ public class GeneratorParameters {
|
||||||
RootClass rootClass,
|
RootClass rootClass,
|
||||||
BiConsumer<String,String> parameterCollector) {
|
BiConsumer<String,String> parameterCollector) {
|
||||||
|
|
||||||
final ConfigurationService configService =
|
final ConfigurationService configService = identifierValue
|
||||||
identifierValue.getMetadata().getMetadataBuildingOptions().getServiceRegistry()
|
.getMetadata()
|
||||||
.requireService( ConfigurationService.class );
|
.getMetadataBuildingOptions()
|
||||||
|
.getServiceRegistry()
|
||||||
|
.requireService( ConfigurationService.class );
|
||||||
|
|
||||||
// default initial value and allocation size per-JPA defaults
|
// default initial value and allocation size per-JPA defaults
|
||||||
parameterCollector.accept( INITIAL_PARAM, String.valueOf( DEFAULT_INITIAL_VALUE ) );
|
parameterCollector.accept( INITIAL_PARAM, String.valueOf( DEFAULT_INITIAL_VALUE ) );
|
||||||
parameterCollector.accept( INCREMENT_PARAM, String.valueOf( defaultIncrement( configService ) ) );
|
parameterCollector.accept( INCREMENT_PARAM, String.valueOf( defaultIncrement( configService ) ) );
|
||||||
|
|
||||||
|
collectBaselineProperties( identifierValue, dialect, rootClass, parameterCollector );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int fallbackAllocationSize(Annotation generatorAnnotation, MetadataBuildingContext buildingContext) {
|
||||||
|
if ( generatorAnnotation == null ) {
|
||||||
|
final ConfigurationService configService = buildingContext
|
||||||
|
.getBootstrapContext()
|
||||||
|
.getServiceRegistry()
|
||||||
|
.requireService( ConfigurationService.class );
|
||||||
|
final String idNamingStrategy = configService.getSetting( ID_DB_STRUCTURE_NAMING_STRATEGY, StandardConverters.STRING );
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void collectBaselineProperties(
|
||||||
|
SimpleValue identifierValue,
|
||||||
|
Dialect dialect,
|
||||||
|
RootClass rootClass,
|
||||||
|
BiConsumer<String,String> parameterCollector) {
|
||||||
|
|
||||||
|
final ConfigurationService configService = identifierValue
|
||||||
|
.getMetadata()
|
||||||
|
.getMetadataBuildingOptions()
|
||||||
|
.getServiceRegistry()
|
||||||
|
.requireService( ConfigurationService.class );
|
||||||
|
|
||||||
//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
|
||||||
|
@ -144,6 +181,7 @@ public class GeneratorParameters {
|
||||||
(String) settings.get( AvailableSettings.PREFERRED_POOLED_OPTIMIZER )
|
(String) settings.get( AvailableSettings.PREFERRED_POOLED_OPTIMIZER )
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String identityTablesString(Dialect dialect, RootClass rootClass) {
|
public static String identityTablesString(Dialect dialect, RootClass rootClass) {
|
||||||
|
@ -157,10 +195,6 @@ public class GeneratorParameters {
|
||||||
return tables.toString();
|
return tables.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int defaultIncrement(MetadataImplementor metadata) {
|
|
||||||
return defaultIncrement( metadata.getMetadataBuildingOptions().getServiceRegistry().requireService( ConfigurationService.class ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int defaultIncrement(ConfigurationService configService) {
|
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,
|
||||||
|
|
|
@ -24,14 +24,17 @@ import org.hibernate.mapping.IdentifierBag;
|
||||||
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 jakarta.persistence.GeneratedValue;
|
import jakarta.persistence.GeneratedValue;
|
||||||
import jakarta.persistence.SequenceGenerator;
|
import jakarta.persistence.SequenceGenerator;
|
||||||
import jakarta.persistence.TableGenerator;
|
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.createGeneratorFrom;
|
||||||
import static org.hibernate.boot.model.internal.GeneratorBinder.makeIdGenerator;
|
import static org.hibernate.boot.model.internal.GeneratorBinder.makeIdGenerator;
|
||||||
|
import static org.hibernate.boot.model.internal.GeneratorParameters.fallbackAllocationSize;
|
||||||
|
import static org.hibernate.id.IdentifierGenerator.GENERATOR_NAME;
|
||||||
|
import static org.hibernate.id.OptimizableGenerator.INCREMENT_PARAM;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IdGeneratorResolver for handling generators assigned to id-bag mappings
|
* IdGeneratorResolver for handling generators assigned to id-bag mappings
|
||||||
|
@ -41,7 +44,7 @@ import static org.hibernate.boot.model.internal.GeneratorBinder.makeIdGenerator;
|
||||||
public class IdBagIdGeneratorResolverSecondPass implements IdGeneratorResolver {
|
public class IdBagIdGeneratorResolverSecondPass implements IdGeneratorResolver {
|
||||||
private final PersistentClass entityMapping;
|
private final PersistentClass entityMapping;
|
||||||
private final SimpleValue idValue;
|
private final SimpleValue idValue;
|
||||||
private final MemberDetails idAttributeMember;
|
private final MemberDetails idBagMember;
|
||||||
private final String generatorType;
|
private final String generatorType;
|
||||||
private final String generatorName;
|
private final String generatorName;
|
||||||
private final MetadataBuildingContext buildingContext;
|
private final MetadataBuildingContext buildingContext;
|
||||||
|
@ -50,13 +53,13 @@ public class IdBagIdGeneratorResolverSecondPass implements IdGeneratorResolver {
|
||||||
public IdBagIdGeneratorResolverSecondPass(
|
public IdBagIdGeneratorResolverSecondPass(
|
||||||
IdentifierBag idBagMapping,
|
IdentifierBag idBagMapping,
|
||||||
SimpleValue idValue,
|
SimpleValue idValue,
|
||||||
MemberDetails idAttributeMember,
|
MemberDetails idBagMember,
|
||||||
String generatorType,
|
String generatorType,
|
||||||
String generatorName,
|
String generatorName,
|
||||||
MetadataBuildingContext buildingContext) {
|
MetadataBuildingContext buildingContext) {
|
||||||
this.entityMapping = null;
|
this.entityMapping = null;
|
||||||
this.idValue = idValue;
|
this.idValue = idValue;
|
||||||
this.idAttributeMember = idAttributeMember;
|
this.idBagMember = idBagMember;
|
||||||
this.generatorType = generatorType;
|
this.generatorType = generatorType;
|
||||||
this.generatorName = generatorName;
|
this.generatorName = generatorName;
|
||||||
this.buildingContext = buildingContext;
|
this.buildingContext = buildingContext;
|
||||||
|
@ -66,27 +69,27 @@ public class IdBagIdGeneratorResolverSecondPass implements IdGeneratorResolver {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doSecondPass(Map<String, PersistentClass> idGeneratorDefinitionMap) throws MappingException {
|
public void doSecondPass(Map<String, PersistentClass> idGeneratorDefinitionMap) throws MappingException {
|
||||||
final GeneratedValue generatedValue = idAttributeMember.getDirectAnnotationUsage( GeneratedValue.class );
|
final GeneratedValue generatedValue = idBagMember.getDirectAnnotationUsage( GeneratedValue.class );
|
||||||
switch ( generatedValue.strategy() ) {
|
switch ( generatedValue.strategy() ) {
|
||||||
case UUID -> GeneratorAnnotationHelper.handleUuidStrategy( idValue, idAttributeMember, buildingContext );
|
case UUID -> GeneratorAnnotationHelper.handleUuidStrategy( idValue, idBagMember, buildingContext );
|
||||||
case IDENTITY -> GeneratorAnnotationHelper.handleIdentityStrategy( idValue );
|
case IDENTITY -> GeneratorAnnotationHelper.handleIdentityStrategy( idValue );
|
||||||
case SEQUENCE -> handleSequenceStrategy(
|
case SEQUENCE -> handleSequenceStrategy(
|
||||||
generatorName,
|
generatorName,
|
||||||
idValue,
|
idValue,
|
||||||
idAttributeMember,
|
idBagMember,
|
||||||
buildingContext
|
buildingContext
|
||||||
);
|
);
|
||||||
case TABLE -> handleTableStrategy(
|
case TABLE -> handleTableStrategy(
|
||||||
generatorName,
|
generatorName,
|
||||||
entityMapping,
|
entityMapping,
|
||||||
idValue,
|
idValue,
|
||||||
idAttributeMember,
|
idBagMember,
|
||||||
buildingContext
|
buildingContext
|
||||||
);
|
);
|
||||||
case AUTO -> handleAutoStrategy(
|
case AUTO -> handleAutoStrategy(
|
||||||
generatorName,
|
generatorName,
|
||||||
idValue,
|
idValue,
|
||||||
idAttributeMember,
|
idBagMember,
|
||||||
buildingContext
|
buildingContext
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -96,7 +99,7 @@ public class IdBagIdGeneratorResolverSecondPass implements IdGeneratorResolver {
|
||||||
String generatorName,
|
String generatorName,
|
||||||
PersistentClass entityMapping,
|
PersistentClass entityMapping,
|
||||||
SimpleValue idValue,
|
SimpleValue idValue,
|
||||||
MemberDetails idAttributeMember,
|
MemberDetails idBagMember,
|
||||||
MetadataBuildingContext buildingContext) {
|
MetadataBuildingContext buildingContext) {
|
||||||
final InFlightMetadataCollector metadataCollector = buildingContext.getMetadataCollector();
|
final InFlightMetadataCollector metadataCollector = buildingContext.getMetadataCollector();
|
||||||
final GlobalRegistrations globalRegistrations = metadataCollector.getGlobalRegistrations();
|
final GlobalRegistrations globalRegistrations = metadataCollector.getGlobalRegistrations();
|
||||||
|
@ -107,8 +110,8 @@ public class IdBagIdGeneratorResolverSecondPass implements IdGeneratorResolver {
|
||||||
handleTableGenerator(
|
handleTableGenerator(
|
||||||
generatorName,
|
generatorName,
|
||||||
globalTableGenerator.configuration(),
|
globalTableGenerator.configuration(),
|
||||||
configuration,
|
|
||||||
idValue,
|
idValue,
|
||||||
|
idBagMember,
|
||||||
buildingContext
|
buildingContext
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
|
@ -116,13 +119,13 @@ public class IdBagIdGeneratorResolverSecondPass implements IdGeneratorResolver {
|
||||||
|
|
||||||
final TableGenerator localizedTableMatch = GeneratorAnnotationHelper.findLocalizedMatch(
|
final TableGenerator localizedTableMatch = GeneratorAnnotationHelper.findLocalizedMatch(
|
||||||
JpaAnnotations.TABLE_GENERATOR,
|
JpaAnnotations.TABLE_GENERATOR,
|
||||||
idAttributeMember,
|
idBagMember,
|
||||||
TableGenerator::name,
|
TableGenerator::name,
|
||||||
generatorName,
|
generatorName,
|
||||||
buildingContext
|
buildingContext
|
||||||
);
|
);
|
||||||
if ( localizedTableMatch != null ) {
|
if ( localizedTableMatch != null ) {
|
||||||
handleTableGenerator( generatorName, localizedTableMatch, configuration, idValue, buildingContext );
|
handleTableGenerator( generatorName, localizedTableMatch, idValue, idBagMember, buildingContext );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,6 +134,7 @@ public class IdBagIdGeneratorResolverSecondPass implements IdGeneratorResolver {
|
||||||
new TableGeneratorJpaAnnotation( metadataCollector.getSourceModelBuildingContext() ),
|
new TableGeneratorJpaAnnotation( metadataCollector.getSourceModelBuildingContext() ),
|
||||||
entityMapping,
|
entityMapping,
|
||||||
idValue,
|
idValue,
|
||||||
|
idBagMember,
|
||||||
buildingContext
|
buildingContext
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -138,7 +142,7 @@ public class IdBagIdGeneratorResolverSecondPass implements IdGeneratorResolver {
|
||||||
private void handleSequenceStrategy(
|
private void handleSequenceStrategy(
|
||||||
String generatorName,
|
String generatorName,
|
||||||
SimpleValue idValue,
|
SimpleValue idValue,
|
||||||
MemberDetails idAttributeMember,
|
MemberDetails idBagMember,
|
||||||
MetadataBuildingContext buildingContext) {
|
MetadataBuildingContext buildingContext) {
|
||||||
final InFlightMetadataCollector metadataCollector = buildingContext.getMetadataCollector();
|
final InFlightMetadataCollector metadataCollector = buildingContext.getMetadataCollector();
|
||||||
final GlobalRegistrations globalRegistrations = metadataCollector.getGlobalRegistrations();
|
final GlobalRegistrations globalRegistrations = metadataCollector.getGlobalRegistrations();
|
||||||
|
@ -149,8 +153,8 @@ public class IdBagIdGeneratorResolverSecondPass implements IdGeneratorResolver {
|
||||||
handleSequenceGenerator(
|
handleSequenceGenerator(
|
||||||
generatorName,
|
generatorName,
|
||||||
globalSequenceGenerator.configuration(),
|
globalSequenceGenerator.configuration(),
|
||||||
configuration,
|
|
||||||
idValue,
|
idValue,
|
||||||
|
idBagMember,
|
||||||
buildingContext
|
buildingContext
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
|
@ -158,21 +162,21 @@ public class IdBagIdGeneratorResolverSecondPass implements IdGeneratorResolver {
|
||||||
|
|
||||||
final SequenceGenerator localizedSequencedMatch = GeneratorAnnotationHelper.findLocalizedMatch(
|
final SequenceGenerator localizedSequencedMatch = GeneratorAnnotationHelper.findLocalizedMatch(
|
||||||
JpaAnnotations.SEQUENCE_GENERATOR,
|
JpaAnnotations.SEQUENCE_GENERATOR,
|
||||||
idAttributeMember,
|
idBagMember,
|
||||||
SequenceGenerator::name,
|
SequenceGenerator::name,
|
||||||
generatorName,
|
generatorName,
|
||||||
buildingContext
|
buildingContext
|
||||||
);
|
);
|
||||||
if ( localizedSequencedMatch != null ) {
|
if ( localizedSequencedMatch != null ) {
|
||||||
handleSequenceGenerator( generatorName, localizedSequencedMatch, configuration, idValue, buildingContext );
|
handleSequenceGenerator( generatorName, localizedSequencedMatch, idValue, idBagMember, buildingContext );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSequenceGenerator(
|
handleSequenceGenerator(
|
||||||
generatorName,
|
generatorName,
|
||||||
new SequenceGeneratorJpaAnnotation( metadataCollector.getSourceModelBuildingContext() ),
|
new SequenceGeneratorJpaAnnotation( metadataCollector.getSourceModelBuildingContext() ),
|
||||||
configuration,
|
|
||||||
idValue,
|
idValue,
|
||||||
|
idBagMember,
|
||||||
buildingContext
|
buildingContext
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -180,7 +184,7 @@ public class IdBagIdGeneratorResolverSecondPass implements IdGeneratorResolver {
|
||||||
private void handleAutoStrategy(
|
private void handleAutoStrategy(
|
||||||
String generatorName,
|
String generatorName,
|
||||||
SimpleValue idValue,
|
SimpleValue idValue,
|
||||||
MemberDetails idAttributeMember,
|
MemberDetails idBagMember,
|
||||||
MetadataBuildingContext buildingContext) {
|
MetadataBuildingContext buildingContext) {
|
||||||
final GlobalRegistrations globalRegistrations =
|
final GlobalRegistrations globalRegistrations =
|
||||||
buildingContext.getMetadataCollector().getGlobalRegistrations();
|
buildingContext.getMetadataCollector().getGlobalRegistrations();
|
||||||
|
@ -191,8 +195,8 @@ public class IdBagIdGeneratorResolverSecondPass implements IdGeneratorResolver {
|
||||||
handleSequenceGenerator(
|
handleSequenceGenerator(
|
||||||
generatorName,
|
generatorName,
|
||||||
globalSequenceGenerator.configuration(),
|
globalSequenceGenerator.configuration(),
|
||||||
configuration,
|
|
||||||
idValue,
|
idValue,
|
||||||
|
idBagMember,
|
||||||
buildingContext
|
buildingContext
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
|
@ -204,8 +208,8 @@ public class IdBagIdGeneratorResolverSecondPass implements IdGeneratorResolver {
|
||||||
handleTableGenerator(
|
handleTableGenerator(
|
||||||
generatorName,
|
generatorName,
|
||||||
globalTableGenerator.configuration(),
|
globalTableGenerator.configuration(),
|
||||||
configuration,
|
|
||||||
idValue,
|
idValue,
|
||||||
|
idBagMember,
|
||||||
buildingContext
|
buildingContext
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
|
@ -230,62 +234,98 @@ public class IdBagIdGeneratorResolverSecondPass implements IdGeneratorResolver {
|
||||||
|
|
||||||
final SequenceGenerator localizedSequencedMatch = GeneratorAnnotationHelper.findLocalizedMatch(
|
final SequenceGenerator localizedSequencedMatch = GeneratorAnnotationHelper.findLocalizedMatch(
|
||||||
JpaAnnotations.SEQUENCE_GENERATOR,
|
JpaAnnotations.SEQUENCE_GENERATOR,
|
||||||
idAttributeMember,
|
idBagMember,
|
||||||
SequenceGenerator::name,
|
SequenceGenerator::name,
|
||||||
generatorName,
|
generatorName,
|
||||||
buildingContext
|
buildingContext
|
||||||
);
|
);
|
||||||
if ( localizedSequencedMatch != null ) {
|
if ( localizedSequencedMatch != null ) {
|
||||||
handleSequenceGenerator( generatorName, localizedSequencedMatch, configuration, idValue, buildingContext );
|
handleSequenceGenerator( generatorName, localizedSequencedMatch, idValue, idBagMember, buildingContext );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final TableGenerator localizedTableMatch = GeneratorAnnotationHelper.findLocalizedMatch(
|
final TableGenerator localizedTableMatch = GeneratorAnnotationHelper.findLocalizedMatch(
|
||||||
JpaAnnotations.TABLE_GENERATOR,
|
JpaAnnotations.TABLE_GENERATOR,
|
||||||
idAttributeMember,
|
idBagMember,
|
||||||
TableGenerator::name,
|
TableGenerator::name,
|
||||||
generatorName,
|
generatorName,
|
||||||
buildingContext
|
buildingContext
|
||||||
);
|
);
|
||||||
if ( localizedTableMatch != null ) {
|
if ( localizedTableMatch != null ) {
|
||||||
handleTableGenerator( generatorName, localizedTableMatch, configuration, idValue, buildingContext );
|
handleTableGenerator( generatorName, localizedTableMatch, idValue, idBagMember, buildingContext );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
makeIdGenerator( idValue, idAttributeMember, generatorType, generatorName, buildingContext, null );
|
makeIdGenerator( idValue, idBagMember, generatorType, generatorName, buildingContext, null );
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void handleSequenceGenerator(
|
public static void handleSequenceGenerator(
|
||||||
String generatorName,
|
String nameFromGeneratedValue,
|
||||||
SequenceGenerator generatorConfig,
|
SequenceGenerator generatorAnnotation,
|
||||||
Map<String,String> configuration,
|
|
||||||
SimpleValue idValue,
|
SimpleValue idValue,
|
||||||
MetadataBuildingContext context) {
|
MemberDetails idBagMember,
|
||||||
applyBaselineConfiguration( generatorConfig, idValue, null, context, configuration::put );
|
MetadataBuildingContext buildingContext) {
|
||||||
SequenceStyleGenerator.applyConfiguration( generatorConfig, configuration::put );
|
idValue.setCustomIdGeneratorCreator( (creationContext) -> {
|
||||||
createGeneratorFrom(
|
final BeanContainer beanContainer = GeneratorBinder.beanContainer( buildingContext );
|
||||||
new IdentifierGeneratorDefinition( generatorName, SequenceStyleGenerator.class.getName(), configuration ),
|
final SequenceStyleGenerator identifierGenerator = GeneratorBinder.instantiateGenerator(
|
||||||
idValue,
|
beanContainer,
|
||||||
(Map) configuration,
|
SequenceStyleGenerator.class
|
||||||
context
|
);
|
||||||
);
|
GeneratorAnnotationHelper.prepareForUse(
|
||||||
|
identifierGenerator,
|
||||||
|
generatorAnnotation,
|
||||||
|
idBagMember,
|
||||||
|
properties -> {
|
||||||
|
if ( generatorAnnotation != null ) {
|
||||||
|
properties.put( GENERATOR_NAME, generatorAnnotation.name() );
|
||||||
|
}
|
||||||
|
else if ( nameFromGeneratedValue != null ) {
|
||||||
|
properties.put( GENERATOR_NAME, nameFromGeneratedValue );
|
||||||
|
}
|
||||||
|
// we need to better handle default allocation-size here...
|
||||||
|
properties.put( INCREMENT_PARAM, fallbackAllocationSize( generatorAnnotation, buildingContext ) );
|
||||||
|
},
|
||||||
|
generatorAnnotation == null
|
||||||
|
? null
|
||||||
|
: (a, properties) -> SequenceStyleGenerator.applyConfiguration( generatorAnnotation, properties::put ),
|
||||||
|
creationContext
|
||||||
|
);
|
||||||
|
return identifierGenerator;
|
||||||
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void handleTableGenerator(
|
public static void handleTableGenerator(
|
||||||
String generatorName,
|
String nameFromGeneratedValue,
|
||||||
TableGenerator generatorConfig,
|
TableGenerator generatorAnnotation,
|
||||||
Map<String,String> configuration,
|
|
||||||
SimpleValue idValue,
|
SimpleValue idValue,
|
||||||
MetadataBuildingContext context) {
|
MemberDetails idBagMember,
|
||||||
GeneratorAnnotationHelper.applyBaselineConfiguration( generatorConfig, idValue, null, context, configuration::put );
|
MetadataBuildingContext buildingContext) {
|
||||||
org.hibernate.id.enhanced.TableGenerator.applyConfiguration( generatorConfig, configuration::put );
|
idValue.setCustomIdGeneratorCreator( (creationContext) -> {
|
||||||
|
final BeanContainer beanContainer = GeneratorBinder.beanContainer( buildingContext );
|
||||||
createGeneratorFrom(
|
final org.hibernate.id.enhanced.TableGenerator identifierGenerator = GeneratorBinder.instantiateGenerator(
|
||||||
new IdentifierGeneratorDefinition( generatorName, org.hibernate.id.enhanced.TableGenerator.class.getName(), configuration ),
|
beanContainer,
|
||||||
idValue,
|
org.hibernate.id.enhanced.TableGenerator.class
|
||||||
(Map) configuration,
|
);
|
||||||
context
|
GeneratorAnnotationHelper.prepareForUse(
|
||||||
);
|
identifierGenerator,
|
||||||
|
generatorAnnotation,
|
||||||
|
idBagMember,
|
||||||
|
properties -> {
|
||||||
|
if ( generatorAnnotation != null ) {
|
||||||
|
properties.put( GENERATOR_NAME, generatorAnnotation.name() );
|
||||||
|
}
|
||||||
|
else if ( nameFromGeneratedValue != null ) {
|
||||||
|
properties.put( GENERATOR_NAME, nameFromGeneratedValue );
|
||||||
|
}
|
||||||
|
// we need to better handle default allocation-size here...
|
||||||
|
properties.put( INCREMENT_PARAM, fallbackAllocationSize( generatorAnnotation, buildingContext ) );
|
||||||
|
},
|
||||||
|
generatorAnnotation == null
|
||||||
|
? null
|
||||||
|
: (a, properties) -> org.hibernate.id.enhanced.TableGenerator.applyConfiguration( generatorAnnotation, properties::put ),
|
||||||
|
creationContext
|
||||||
|
);
|
||||||
|
return identifierGenerator;
|
||||||
|
} );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,16 +4,11 @@
|
||||||
*/
|
*/
|
||||||
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.Locale;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
import org.hibernate.annotations.GenericGenerator;
|
import org.hibernate.annotations.GenericGenerator;
|
||||||
import org.hibernate.annotations.IdGeneratorType;
|
|
||||||
import org.hibernate.boot.model.IdentifierGeneratorDefinition;
|
import org.hibernate.boot.model.IdentifierGeneratorDefinition;
|
||||||
import org.hibernate.boot.models.HibernateAnnotations;
|
import org.hibernate.boot.models.HibernateAnnotations;
|
||||||
import org.hibernate.boot.models.JpaAnnotations;
|
import org.hibernate.boot.models.JpaAnnotations;
|
||||||
|
@ -21,32 +16,19 @@ import org.hibernate.boot.models.spi.GenericGeneratorRegistration;
|
||||||
import org.hibernate.boot.models.spi.GlobalRegistrations;
|
import org.hibernate.boot.models.spi.GlobalRegistrations;
|
||||||
import org.hibernate.boot.models.spi.SequenceGeneratorRegistration;
|
import org.hibernate.boot.models.spi.SequenceGeneratorRegistration;
|
||||||
import org.hibernate.boot.models.spi.TableGeneratorRegistration;
|
import org.hibernate.boot.models.spi.TableGeneratorRegistration;
|
||||||
import org.hibernate.boot.spi.InFlightMetadataCollector;
|
|
||||||
import org.hibernate.boot.spi.MetadataBuildingContext;
|
import org.hibernate.boot.spi.MetadataBuildingContext;
|
||||||
import org.hibernate.engine.config.spi.ConfigurationService;
|
|
||||||
import org.hibernate.engine.config.spi.StandardConverters;
|
|
||||||
import org.hibernate.generator.Generator;
|
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 jakarta.persistence.GeneratedValue;
|
import jakarta.persistence.GeneratedValue;
|
||||||
import jakarta.persistence.SequenceGenerator;
|
import jakarta.persistence.SequenceGenerator;
|
||||||
import jakarta.persistence.TableGenerator;
|
import jakarta.persistence.TableGenerator;
|
||||||
|
|
||||||
import static org.hibernate.boot.model.internal.GeneratorBinder.callConfigure;
|
import static org.hibernate.boot.model.internal.GeneratorAnnotationHelper.findLocalizedMatch;
|
||||||
import static org.hibernate.boot.model.internal.GeneratorBinder.instantiateGenerator;
|
import static org.hibernate.boot.model.internal.GeneratorAnnotationHelper.handleSequenceGenerator;
|
||||||
import static org.hibernate.boot.model.internal.GeneratorStrategies.mapLegacyNamedGenerator;
|
import static org.hibernate.boot.model.internal.GeneratorStrategies.mapLegacyNamedGenerator;
|
||||||
import static org.hibernate.cfg.MappingSettings.ID_DB_STRUCTURE_NAMING_STRATEGY;
|
|
||||||
import static org.hibernate.id.IdentifierGenerator.GENERATOR_NAME;
|
|
||||||
import static org.hibernate.id.OptimizableGenerator.INCREMENT_PARAM;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SecondPass implementing delayed resolution of id-generators associated with an entity.
|
* SecondPass implementing delayed resolution of id-generators associated with an entity.
|
||||||
|
@ -55,50 +37,25 @@ import static org.hibernate.id.OptimizableGenerator.INCREMENT_PARAM;
|
||||||
*
|
*
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class IdGeneratorResolverSecondPass implements IdGeneratorResolver {
|
public class IdGeneratorResolverSecondPass extends AbstractEntityIdGeneratorResolver {
|
||||||
private final PersistentClass entityMapping;
|
|
||||||
private final SimpleValue idValue;
|
|
||||||
private final MemberDetails idMember;
|
|
||||||
private final GeneratedValue generatedValue;
|
|
||||||
private final MetadataBuildingContext buildingContext;
|
|
||||||
|
|
||||||
public IdGeneratorResolverSecondPass(
|
public IdGeneratorResolverSecondPass(
|
||||||
PersistentClass entityMapping,
|
PersistentClass entityMapping,
|
||||||
SimpleValue idValue,
|
SimpleValue idValue,
|
||||||
MemberDetails idMember,
|
MemberDetails idMember,
|
||||||
GeneratedValue generatedValue,
|
GeneratedValue generatedValue,
|
||||||
MetadataBuildingContext buildingContext) {
|
MetadataBuildingContext buildingContext) {
|
||||||
this.entityMapping = entityMapping;
|
super( entityMapping, idValue, idMember, generatedValue, buildingContext );
|
||||||
this.idValue = idValue;
|
|
||||||
this.idMember = idMember;
|
|
||||||
this.generatedValue = generatedValue;
|
|
||||||
this.buildingContext = buildingContext;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
// SEQUENCE
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doSecondPass(Map<String, PersistentClass> persistentClasses) throws MappingException {
|
protected void handleUnnamedSequenceGenerator() {
|
||||||
switch ( generatedValue.strategy() ) {
|
|
||||||
case UUID -> GeneratorAnnotationHelper.handleUuidStrategy( idValue, idMember, buildingContext );
|
|
||||||
case IDENTITY -> GeneratorAnnotationHelper.handleIdentityStrategy( idValue );
|
|
||||||
case SEQUENCE -> handleSequenceStrategy();
|
|
||||||
case TABLE -> handleTableStrategy();
|
|
||||||
case AUTO -> handleAutoStrategy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleSequenceStrategy() {
|
|
||||||
if ( generatedValue.generator().isEmpty() ) {
|
|
||||||
handleUnnamedSequenceGenerator();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
handleNamedSequenceGenerator();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleUnnamedSequenceGenerator() {
|
|
||||||
// todo (7.0) : null or entityMapping.getJpaEntityName() for "name from GeneratedValue"?
|
// todo (7.0) : null or entityMapping.getJpaEntityName() for "name from GeneratedValue"?
|
||||||
|
|
||||||
final SequenceGenerator localizedMatch = GeneratorAnnotationHelper.findLocalizedMatch(
|
final SequenceGenerator localizedMatch = findLocalizedMatch(
|
||||||
JpaAnnotations.SEQUENCE_GENERATOR,
|
JpaAnnotations.SEQUENCE_GENERATOR,
|
||||||
idMember,
|
idMember,
|
||||||
null,
|
null,
|
||||||
|
@ -106,17 +63,18 @@ public class IdGeneratorResolverSecondPass implements IdGeneratorResolver {
|
||||||
buildingContext
|
buildingContext
|
||||||
);
|
);
|
||||||
if ( localizedMatch != null ) {
|
if ( localizedMatch != null ) {
|
||||||
handleSequenceGenerator( null, localizedMatch );
|
handleSequenceGenerator( null, localizedMatch, idValue, idMember, buildingContext );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSequenceGenerator( null, null );
|
handleSequenceGenerator( null, null, idValue, idMember, buildingContext );
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleNamedSequenceGenerator() {
|
@Override
|
||||||
|
protected void handleNamedSequenceGenerator() {
|
||||||
final String generator = generatedValue.generator();
|
final String generator = generatedValue.generator();
|
||||||
|
|
||||||
final SequenceGenerator localizedMatch = GeneratorAnnotationHelper.findLocalizedMatch(
|
final SequenceGenerator localizedMatch = findLocalizedMatch(
|
||||||
JpaAnnotations.SEQUENCE_GENERATOR,
|
JpaAnnotations.SEQUENCE_GENERATOR,
|
||||||
idMember,
|
idMember,
|
||||||
SequenceGenerator::name,
|
SequenceGenerator::name,
|
||||||
|
@ -124,7 +82,7 @@ public class IdGeneratorResolverSecondPass implements IdGeneratorResolver {
|
||||||
buildingContext
|
buildingContext
|
||||||
);
|
);
|
||||||
if ( localizedMatch != null ) {
|
if ( localizedMatch != null ) {
|
||||||
handleSequenceGenerator( generator, localizedMatch );
|
handleSequenceGenerator( generator, localizedMatch, idValue, idMember, buildingContext );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,13 +93,13 @@ public class IdGeneratorResolverSecondPass implements IdGeneratorResolver {
|
||||||
.getSequenceGeneratorRegistrations()
|
.getSequenceGeneratorRegistrations()
|
||||||
.get( generator );
|
.get( generator );
|
||||||
if ( globalMatch != null ) {
|
if ( globalMatch != null ) {
|
||||||
handleSequenceGenerator( generator, globalMatch.configuration() );
|
handleSequenceGenerator( generator, globalMatch.configuration(), idValue, idMember, buildingContext );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
validateSequenceGeneration();
|
validateSequenceGeneration();
|
||||||
|
|
||||||
handleSequenceGenerator( generator, null );
|
handleSequenceGenerator( generator, null, idValue, idMember, buildingContext );
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateSequenceGeneration() {
|
private void validateSequenceGeneration() {
|
||||||
|
@ -178,19 +136,15 @@ public class IdGeneratorResolverSecondPass implements IdGeneratorResolver {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleTableStrategy() {
|
|
||||||
if ( generatedValue.generator().isEmpty() ) {
|
|
||||||
handleUnnamedTableGenerator();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
handleNamedTableGenerator();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleUnnamedTableGenerator() {
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
// TABLE
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void handleUnnamedTableGenerator() {
|
||||||
// todo (7.0) : null or entityMapping.getJpaEntityName() for "name from GeneratedValue"?
|
// todo (7.0) : null or entityMapping.getJpaEntityName() for "name from GeneratedValue"?
|
||||||
|
|
||||||
final TableGenerator localizedMatch = GeneratorAnnotationHelper.findLocalizedMatch(
|
final TableGenerator localizedMatch = findLocalizedMatch(
|
||||||
JpaAnnotations.TABLE_GENERATOR,
|
JpaAnnotations.TABLE_GENERATOR,
|
||||||
idMember,
|
idMember,
|
||||||
null,
|
null,
|
||||||
|
@ -200,10 +154,11 @@ public class IdGeneratorResolverSecondPass implements IdGeneratorResolver {
|
||||||
handleTableGenerator( null, localizedMatch );
|
handleTableGenerator( null, localizedMatch );
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleNamedTableGenerator() {
|
@Override
|
||||||
|
protected void handleNamedTableGenerator() {
|
||||||
final String generator = generatedValue.generator();
|
final String generator = generatedValue.generator();
|
||||||
|
|
||||||
final TableGenerator localizedTableMatch = GeneratorAnnotationHelper.findLocalizedMatch(
|
final TableGenerator localizedTableMatch = findLocalizedMatch(
|
||||||
JpaAnnotations.TABLE_GENERATOR,
|
JpaAnnotations.TABLE_GENERATOR,
|
||||||
idMember,
|
idMember,
|
||||||
TableGenerator::name,
|
TableGenerator::name,
|
||||||
|
@ -263,19 +218,15 @@ public class IdGeneratorResolverSecondPass implements IdGeneratorResolver {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleAutoStrategy() {
|
|
||||||
if ( generatedValue.generator().isEmpty() ) {
|
|
||||||
handleUnnamedAutoGenerator();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
handleNamedAutoGenerator();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleUnnamedAutoGenerator() {
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
// AUTO
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void handleUnnamedAutoGenerator() {
|
||||||
// todo (7.0) : null or entityMapping.getJpaEntityName() for "name from GeneratedValue"?
|
// todo (7.0) : null or entityMapping.getJpaEntityName() for "name from GeneratedValue"?
|
||||||
|
|
||||||
final SequenceGenerator localizedSequenceMatch = GeneratorAnnotationHelper.findLocalizedMatch(
|
final SequenceGenerator localizedSequenceMatch = findLocalizedMatch(
|
||||||
JpaAnnotations.SEQUENCE_GENERATOR,
|
JpaAnnotations.SEQUENCE_GENERATOR,
|
||||||
idMember,
|
idMember,
|
||||||
null,
|
null,
|
||||||
|
@ -283,11 +234,11 @@ public class IdGeneratorResolverSecondPass implements IdGeneratorResolver {
|
||||||
buildingContext
|
buildingContext
|
||||||
);
|
);
|
||||||
if ( localizedSequenceMatch != null ) {
|
if ( localizedSequenceMatch != null ) {
|
||||||
handleSequenceGenerator( null, localizedSequenceMatch );
|
handleSequenceGenerator( null, localizedSequenceMatch, idValue, idMember, buildingContext );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final TableGenerator localizedTableMatch = GeneratorAnnotationHelper.findLocalizedMatch(
|
final TableGenerator localizedTableMatch = findLocalizedMatch(
|
||||||
JpaAnnotations.TABLE_GENERATOR,
|
JpaAnnotations.TABLE_GENERATOR,
|
||||||
idMember,
|
idMember,
|
||||||
null,
|
null,
|
||||||
|
@ -299,7 +250,7 @@ public class IdGeneratorResolverSecondPass implements IdGeneratorResolver {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final GenericGenerator localizedGenericMatch = GeneratorAnnotationHelper.findLocalizedMatch(
|
final GenericGenerator localizedGenericMatch = findLocalizedMatch(
|
||||||
HibernateAnnotations.GENERIC_GENERATOR,
|
HibernateAnnotations.GENERIC_GENERATOR,
|
||||||
idMember,
|
idMember,
|
||||||
null,
|
null,
|
||||||
|
@ -317,16 +268,25 @@ public class IdGeneratorResolverSecondPass implements IdGeneratorResolver {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( handleAsMetaAnnotated() ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if ( idMember.getType().isImplementor( UUID.class )
|
if ( idMember.getType().isImplementor( UUID.class )
|
||||||
|| idMember.getType().isImplementor( String.class ) ) {
|
|| idMember.getType().isImplementor( String.class ) ) {
|
||||||
GeneratorAnnotationHelper.handleUuidStrategy( idValue, idMember, buildingContext );
|
GeneratorAnnotationHelper.handleUuidStrategy( idValue, idMember, buildingContext );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSequenceGenerator( null, null );
|
if ( handleAsLegacyGenerator() ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
handleSequenceGenerator( null, null, idValue, idMember, buildingContext );
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleNamedAutoGenerator() {
|
@Override
|
||||||
|
protected void handleNamedAutoGenerator() {
|
||||||
if ( handleAsLocalAutoGenerator() ) {
|
if ( handleAsLocalAutoGenerator() ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -347,29 +307,7 @@ public class IdGeneratorResolverSecondPass implements IdGeneratorResolver {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final InFlightMetadataCollector metadataCollector = buildingContext.getMetadataCollector();
|
if ( handleAsMetaAnnotated() ) {
|
||||||
final List<? extends Annotation> metaAnnotated =
|
|
||||||
idMember.getMetaAnnotated( IdGeneratorType.class, metadataCollector.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 = instantiateGenerator(
|
|
||||||
beanContainer,
|
|
||||||
markerAnnotation.value()
|
|
||||||
);
|
|
||||||
final Map<String,Object> configuration = new HashMap<>();
|
|
||||||
GeneratorParameters.collectParameters(
|
|
||||||
idValue,
|
|
||||||
metadataCollector.getDatabase().getDialect(),
|
|
||||||
entityMapping.getRootClass(),
|
|
||||||
configuration::put
|
|
||||||
);
|
|
||||||
callConfigure( creationContext, identifierGenerator, configuration, idValue );
|
|
||||||
return identifierGenerator;
|
|
||||||
} );
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -379,14 +317,18 @@ public class IdGeneratorResolverSecondPass implements IdGeneratorResolver {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSequenceGenerator(generator, null );
|
if ( handleAsLegacyGenerator() ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
handleSequenceGenerator( generator, null, idValue, idMember, buildingContext );
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean handleAsLocalAutoGenerator() {
|
private boolean handleAsLocalAutoGenerator() {
|
||||||
final String generator = generatedValue.generator();
|
final String generator = generatedValue.generator();
|
||||||
assert !generator.isEmpty();
|
assert !generator.isEmpty();
|
||||||
|
|
||||||
final SequenceGenerator localizedSequenceMatch = GeneratorAnnotationHelper.findLocalizedMatch(
|
final SequenceGenerator localizedSequenceMatch = findLocalizedMatch(
|
||||||
JpaAnnotations.SEQUENCE_GENERATOR,
|
JpaAnnotations.SEQUENCE_GENERATOR,
|
||||||
idMember,
|
idMember,
|
||||||
SequenceGenerator::name,
|
SequenceGenerator::name,
|
||||||
|
@ -394,11 +336,11 @@ public class IdGeneratorResolverSecondPass implements IdGeneratorResolver {
|
||||||
buildingContext
|
buildingContext
|
||||||
);
|
);
|
||||||
if ( localizedSequenceMatch != null ) {
|
if ( localizedSequenceMatch != null ) {
|
||||||
handleSequenceGenerator( generator, localizedSequenceMatch );
|
handleSequenceGenerator( generator, localizedSequenceMatch, idValue, idMember, buildingContext );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
final TableGenerator localizedTableMatch = GeneratorAnnotationHelper.findLocalizedMatch(
|
final TableGenerator localizedTableMatch = findLocalizedMatch(
|
||||||
JpaAnnotations.TABLE_GENERATOR,
|
JpaAnnotations.TABLE_GENERATOR,
|
||||||
idMember,
|
idMember,
|
||||||
TableGenerator::name,
|
TableGenerator::name,
|
||||||
|
@ -410,7 +352,7 @@ public class IdGeneratorResolverSecondPass implements IdGeneratorResolver {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
final GenericGenerator localizedGenericMatch = GeneratorAnnotationHelper.findLocalizedMatch(
|
final GenericGenerator localizedGenericMatch = findLocalizedMatch(
|
||||||
HibernateAnnotations.GENERIC_GENERATOR,
|
HibernateAnnotations.GENERIC_GENERATOR,
|
||||||
idMember,
|
idMember,
|
||||||
GenericGenerator::name,
|
GenericGenerator::name,
|
||||||
|
@ -439,7 +381,7 @@ public class IdGeneratorResolverSecondPass implements IdGeneratorResolver {
|
||||||
final SequenceGeneratorRegistration globalSequenceMatch =
|
final SequenceGeneratorRegistration globalSequenceMatch =
|
||||||
globalRegistrations.getSequenceGeneratorRegistrations().get( generator );
|
globalRegistrations.getSequenceGeneratorRegistrations().get( generator );
|
||||||
if ( globalSequenceMatch != null ) {
|
if ( globalSequenceMatch != null ) {
|
||||||
handleSequenceGenerator( generator, globalSequenceMatch.configuration() );
|
handleSequenceGenerator( generator, globalSequenceMatch.configuration(), idValue, idMember, buildingContext );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -466,97 +408,15 @@ public class IdGeneratorResolverSecondPass implements IdGeneratorResolver {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleSequenceGenerator(String nameFromGeneratedValue, SequenceGenerator generator) {
|
private void handleTableGenerator(String nameFromGeneratedValue, TableGenerator generatorAnnotation) {
|
||||||
createGeneratorFrom( SequenceStyleGenerator.class, extractConfiguration( nameFromGeneratedValue, generator ) );
|
GeneratorAnnotationHelper.handleTableGenerator(
|
||||||
}
|
nameFromGeneratedValue,
|
||||||
|
generatorAnnotation,
|
||||||
private Map<String,Object> extractConfiguration(String nameFromGenerated, SequenceGenerator generator) {
|
entityMapping,
|
||||||
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, configuration::put );
|
|
||||||
}
|
|
||||||
|
|
||||||
return configuration;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void applyCommonConfiguration(Map<String, Object> configuration, Annotation generatorAnnotation) {
|
|
||||||
GeneratorParameters.collectParameters(
|
|
||||||
idValue,
|
idValue,
|
||||||
buildingContext.getMetadataCollector().getDatabase().getDialect(),
|
idMember,
|
||||||
entityMapping.getRootClass(),
|
buildingContext
|
||||||
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 ConfigurationService configService =
|
|
||||||
buildingContext.getBootstrapContext().getServiceRegistry()
|
|
||||||
.requireService( ConfigurationService.class );
|
|
||||||
final String idNamingStrategy =
|
|
||||||
configService.getSetting( ID_DB_STRUCTURE_NAMING_STRATEGY, StandardConverters.STRING );
|
|
||||||
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) {
|
|
||||||
createGeneratorFrom( org.hibernate.id.enhanced.TableGenerator.class,
|
|
||||||
extractConfiguration( nameFromGeneratedValue, generator ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
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, 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 = instantiateGenerator( beanContainer, generatorClass );
|
|
||||||
callConfigure( creationContext, identifierGenerator, configuration, idValue );
|
|
||||||
if ( identifierGenerator instanceof IdentityGenerator ) {
|
|
||||||
idValue.setColumnToIdentity();
|
|
||||||
}
|
|
||||||
return identifierGenerator;
|
|
||||||
} );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,13 +4,8 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.boot.model.internal;
|
package org.hibernate.boot.model.internal;
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.UUID;
|
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.SequenceGeneratorJpaAnnotation;
|
||||||
import org.hibernate.boot.models.annotations.internal.TableGeneratorJpaAnnotation;
|
import org.hibernate.boot.models.annotations.internal.TableGeneratorJpaAnnotation;
|
||||||
import org.hibernate.boot.models.spi.GenericGeneratorRegistration;
|
import org.hibernate.boot.models.spi.GenericGeneratorRegistration;
|
||||||
|
@ -19,28 +14,16 @@ import org.hibernate.boot.models.spi.SequenceGeneratorRegistration;
|
||||||
import org.hibernate.boot.models.spi.TableGeneratorRegistration;
|
import org.hibernate.boot.models.spi.TableGeneratorRegistration;
|
||||||
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.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.PersistentClass;
|
||||||
import org.hibernate.mapping.SimpleValue;
|
import org.hibernate.mapping.SimpleValue;
|
||||||
import org.hibernate.models.spi.MemberDetails;
|
import org.hibernate.models.spi.MemberDetails;
|
||||||
|
|
||||||
import jakarta.persistence.GeneratedValue;
|
import jakarta.persistence.GeneratedValue;
|
||||||
import jakarta.persistence.SequenceGenerator;
|
|
||||||
|
|
||||||
import static org.hibernate.boot.model.internal.GeneratorAnnotationHelper.*;
|
import static org.hibernate.boot.model.internal.GeneratorAnnotationHelper.handleGenericGenerator;
|
||||||
|
import static org.hibernate.boot.model.internal.GeneratorAnnotationHelper.handleSequenceGenerator;
|
||||||
|
import static org.hibernate.boot.model.internal.GeneratorAnnotationHelper.handleTableGenerator;
|
||||||
import static org.hibernate.boot.model.internal.GeneratorAnnotationHelper.handleUuidStrategy;
|
import static org.hibernate.boot.model.internal.GeneratorAnnotationHelper.handleUuidStrategy;
|
||||||
import static org.hibernate.boot.model.internal.GeneratorParameters.identityTablesString;
|
|
||||||
import static org.hibernate.boot.model.internal.GeneratorStrategies.mapLegacyNamedGenerator;
|
|
||||||
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
|
* SecondPass implementing delayed resolution of id-generators associated with an entity
|
||||||
|
@ -57,46 +40,18 @@ import static org.hibernate.id.PersistentIdentifierGenerator.TABLES;
|
||||||
*
|
*
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class StrictIdGeneratorResolverSecondPass implements IdGeneratorResolver {
|
public class StrictIdGeneratorResolverSecondPass extends AbstractEntityIdGeneratorResolver {
|
||||||
private final PersistentClass entityMapping;
|
|
||||||
private final SimpleValue idValue;
|
|
||||||
private final MemberDetails idMember;
|
|
||||||
|
|
||||||
private final MetadataBuildingContext buildingContext;
|
|
||||||
|
|
||||||
public StrictIdGeneratorResolverSecondPass(
|
public StrictIdGeneratorResolverSecondPass(
|
||||||
PersistentClass entityMapping,
|
PersistentClass entityMapping,
|
||||||
SimpleValue idValue,
|
SimpleValue idValue,
|
||||||
MemberDetails idMember,
|
MemberDetails idMember,
|
||||||
|
GeneratedValue generatedValue,
|
||||||
MetadataBuildingContext buildingContext) {
|
MetadataBuildingContext buildingContext) {
|
||||||
this.entityMapping = entityMapping;
|
super( entityMapping, idValue, idMember, generatedValue, buildingContext );
|
||||||
this.idValue = idValue;
|
|
||||||
this.idMember = idMember;
|
|
||||||
this.buildingContext = buildingContext;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doSecondPass(Map<String, PersistentClass> persistentClasses) throws MappingException {
|
protected void handleUnnamedSequenceGenerator() {
|
||||||
final GeneratedValue generatedValue = idMember.getDirectAnnotationUsage( GeneratedValue.class );
|
|
||||||
switch ( generatedValue.strategy() ) {
|
|
||||||
case UUID -> handleUuidStrategy( idValue, idMember, buildingContext );
|
|
||||||
case IDENTITY -> handleIdentityStrategy( idValue );
|
|
||||||
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() {
|
|
||||||
final InFlightMetadataCollector metadataCollector = buildingContext.getMetadataCollector();
|
final InFlightMetadataCollector metadataCollector = buildingContext.getMetadataCollector();
|
||||||
|
|
||||||
// according to the spec, this should locate a generator with the same name as the entity-name
|
// according to the spec, this should locate a generator with the same name as the entity-name
|
||||||
|
@ -107,7 +62,6 @@ public class StrictIdGeneratorResolverSecondPass implements IdGeneratorResolver
|
||||||
handleSequenceGenerator(
|
handleSequenceGenerator(
|
||||||
entityMapping.getJpaEntityName(),
|
entityMapping.getJpaEntityName(),
|
||||||
globalMatch.configuration(),
|
globalMatch.configuration(),
|
||||||
entityMapping,
|
|
||||||
idValue,
|
idValue,
|
||||||
idMember,
|
idMember,
|
||||||
buildingContext
|
buildingContext
|
||||||
|
@ -118,14 +72,14 @@ public class StrictIdGeneratorResolverSecondPass implements IdGeneratorResolver
|
||||||
handleSequenceGenerator(
|
handleSequenceGenerator(
|
||||||
entityMapping.getJpaEntityName(),
|
entityMapping.getJpaEntityName(),
|
||||||
new SequenceGeneratorJpaAnnotation( metadataCollector.getSourceModelBuildingContext() ),
|
new SequenceGeneratorJpaAnnotation( metadataCollector.getSourceModelBuildingContext() ),
|
||||||
entityMapping,
|
|
||||||
idValue,
|
idValue,
|
||||||
idMember,
|
idMember,
|
||||||
buildingContext
|
buildingContext
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleNamedSequenceGenerator(GeneratedValue generatedValue) {
|
@Override
|
||||||
|
protected void handleNamedSequenceGenerator() {
|
||||||
final InFlightMetadataCollector metadataCollector = buildingContext.getMetadataCollector();
|
final InFlightMetadataCollector metadataCollector = buildingContext.getMetadataCollector();
|
||||||
|
|
||||||
final SequenceGeneratorRegistration globalMatch =
|
final SequenceGeneratorRegistration globalMatch =
|
||||||
|
@ -135,7 +89,6 @@ public class StrictIdGeneratorResolverSecondPass implements IdGeneratorResolver
|
||||||
handleSequenceGenerator(
|
handleSequenceGenerator(
|
||||||
generatedValue.generator(),
|
generatedValue.generator(),
|
||||||
globalMatch.configuration(),
|
globalMatch.configuration(),
|
||||||
entityMapping,
|
|
||||||
idValue,
|
idValue,
|
||||||
idMember,
|
idMember,
|
||||||
buildingContext
|
buildingContext
|
||||||
|
@ -146,23 +99,14 @@ public class StrictIdGeneratorResolverSecondPass implements IdGeneratorResolver
|
||||||
handleSequenceGenerator(
|
handleSequenceGenerator(
|
||||||
generatedValue.generator(),
|
generatedValue.generator(),
|
||||||
new SequenceGeneratorJpaAnnotation( generatedValue.generator(), metadataCollector.getSourceModelBuildingContext() ),
|
new SequenceGeneratorJpaAnnotation( generatedValue.generator(), metadataCollector.getSourceModelBuildingContext() ),
|
||||||
entityMapping,
|
|
||||||
idValue,
|
idValue,
|
||||||
idMember,
|
idMember,
|
||||||
buildingContext
|
buildingContext
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleTableStrategy(GeneratedValue generatedValue) {
|
@Override
|
||||||
if ( generatedValue.generator().isEmpty() ) {
|
protected void handleUnnamedTableGenerator() {
|
||||||
handleUnnamedTableGenerator();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
handleNamedTableGenerator( generatedValue );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleUnnamedTableGenerator() {
|
|
||||||
final InFlightMetadataCollector metadataCollector = buildingContext.getMetadataCollector();
|
final InFlightMetadataCollector metadataCollector = buildingContext.getMetadataCollector();
|
||||||
|
|
||||||
final TableGeneratorRegistration globalMatch =
|
final TableGeneratorRegistration globalMatch =
|
||||||
|
@ -174,6 +118,7 @@ public class StrictIdGeneratorResolverSecondPass implements IdGeneratorResolver
|
||||||
globalMatch.configuration(),
|
globalMatch.configuration(),
|
||||||
entityMapping,
|
entityMapping,
|
||||||
idValue,
|
idValue,
|
||||||
|
idMember,
|
||||||
buildingContext
|
buildingContext
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
|
@ -184,11 +129,13 @@ public class StrictIdGeneratorResolverSecondPass implements IdGeneratorResolver
|
||||||
new TableGeneratorJpaAnnotation( metadataCollector.getSourceModelBuildingContext() ),
|
new TableGeneratorJpaAnnotation( metadataCollector.getSourceModelBuildingContext() ),
|
||||||
entityMapping,
|
entityMapping,
|
||||||
idValue,
|
idValue,
|
||||||
|
idMember,
|
||||||
buildingContext
|
buildingContext
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleNamedTableGenerator(GeneratedValue generatedValue) {
|
@Override
|
||||||
|
protected void handleNamedTableGenerator() {
|
||||||
final InFlightMetadataCollector metadataCollector = buildingContext.getMetadataCollector();
|
final InFlightMetadataCollector metadataCollector = buildingContext.getMetadataCollector();
|
||||||
|
|
||||||
final TableGeneratorRegistration globalMatch =
|
final TableGeneratorRegistration globalMatch =
|
||||||
|
@ -200,6 +147,7 @@ public class StrictIdGeneratorResolverSecondPass implements IdGeneratorResolver
|
||||||
globalMatch.configuration(),
|
globalMatch.configuration(),
|
||||||
entityMapping,
|
entityMapping,
|
||||||
idValue,
|
idValue,
|
||||||
|
idMember,
|
||||||
buildingContext
|
buildingContext
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -211,14 +159,22 @@ public class StrictIdGeneratorResolverSecondPass implements IdGeneratorResolver
|
||||||
new TableGeneratorJpaAnnotation( generatedValue.generator(), metadataCollector.getSourceModelBuildingContext() ),
|
new TableGeneratorJpaAnnotation( generatedValue.generator(), metadataCollector.getSourceModelBuildingContext() ),
|
||||||
entityMapping,
|
entityMapping,
|
||||||
idValue,
|
idValue,
|
||||||
|
idMember,
|
||||||
buildingContext
|
buildingContext
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleAutoStrategy(GeneratedValue generatedValue) {
|
@Override
|
||||||
final String generator = generatedValue.generator();
|
protected void handleUnnamedAutoGenerator() {
|
||||||
final String globalRegistrationName = generator.isEmpty() ? entityMapping.getJpaEntityName() : generator;
|
handleAutoGenerator( entityMapping.getJpaEntityName() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void handleNamedAutoGenerator() {
|
||||||
|
handleAutoGenerator( generatedValue.generator() );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleAutoGenerator(String globalRegistrationName) {
|
||||||
final InFlightMetadataCollector metadataCollector = buildingContext.getMetadataCollector();
|
final InFlightMetadataCollector metadataCollector = buildingContext.getMetadataCollector();
|
||||||
final GlobalRegistrations globalRegistrations = metadataCollector.getGlobalRegistrations();
|
final GlobalRegistrations globalRegistrations = metadataCollector.getGlobalRegistrations();
|
||||||
|
|
||||||
|
@ -228,7 +184,6 @@ public class StrictIdGeneratorResolverSecondPass implements IdGeneratorResolver
|
||||||
handleSequenceGenerator(
|
handleSequenceGenerator(
|
||||||
globalRegistrationName,
|
globalRegistrationName,
|
||||||
globalSequenceMatch.configuration(),
|
globalSequenceMatch.configuration(),
|
||||||
entityMapping,
|
|
||||||
idValue,
|
idValue,
|
||||||
idMember,
|
idMember,
|
||||||
buildingContext
|
buildingContext
|
||||||
|
@ -244,6 +199,7 @@ public class StrictIdGeneratorResolverSecondPass implements IdGeneratorResolver
|
||||||
globalTableMatch.configuration(),
|
globalTableMatch.configuration(),
|
||||||
entityMapping,
|
entityMapping,
|
||||||
idValue,
|
idValue,
|
||||||
|
idMember,
|
||||||
buildingContext
|
buildingContext
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
|
@ -262,6 +218,10 @@ public class StrictIdGeneratorResolverSecondPass implements IdGeneratorResolver
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( handleAsMetaAnnotated() ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Implicit handling of UUID generation
|
// Implicit handling of UUID generation
|
||||||
if ( idMember.getType().isImplementor( UUID.class )
|
if ( idMember.getType().isImplementor( UUID.class )
|
||||||
|| idMember.getType().isImplementor( String.class ) ) {
|
|| idMember.getType().isImplementor( String.class ) ) {
|
||||||
|
@ -269,85 +229,16 @@ public class StrictIdGeneratorResolverSecondPass implements IdGeneratorResolver
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( handleAsLegacyGenerator() ) {
|
||||||
// Handle a few legacy Hibernate generators...
|
return;
|
||||||
if ( !generator.isEmpty() ) {
|
|
||||||
final Class<? extends Generator> legacyNamedGenerator = mapLegacyNamedGenerator( generator, idValue );
|
|
||||||
if ( legacyNamedGenerator != null ) {
|
|
||||||
final Map<String,String> configuration = buildLegacyGeneratorConfig();
|
|
||||||
//noinspection unchecked,rawtypes
|
|
||||||
GeneratorBinder.createGeneratorFrom(
|
|
||||||
new IdentifierGeneratorDefinition( generator, legacyNamedGenerator.getName(), configuration ),
|
|
||||||
idValue,
|
|
||||||
(Map) configuration,
|
|
||||||
buildingContext
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSequenceGenerator(
|
handleSequenceGenerator(
|
||||||
globalRegistrationName,
|
globalRegistrationName,
|
||||||
new SequenceGeneratorJpaAnnotation( generator, metadataCollector.getSourceModelBuildingContext() ),
|
new SequenceGeneratorJpaAnnotation( generatedValue.generator(), metadataCollector.getSourceModelBuildingContext() ),
|
||||||
entityMapping,
|
|
||||||
idValue,
|
idValue,
|
||||||
idMember,
|
idMember,
|
||||||
buildingContext
|
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, configuration::put );
|
|
||||||
}
|
|
||||||
|
|
||||||
GeneratorBinder.createGeneratorFrom(
|
|
||||||
new IdentifierGeneratorDefinition( generatorName, SequenceStyleGenerator.class.getName(), configuration ),
|
|
||||||
idValue,
|
|
||||||
context
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,6 +75,7 @@ import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
|
import jakarta.persistence.GenerationType;
|
||||||
import jakarta.persistence.TemporalType;
|
import jakarta.persistence.TemporalType;
|
||||||
|
|
||||||
import static java.lang.Integer.parseInt;
|
import static java.lang.Integer.parseInt;
|
||||||
|
@ -620,8 +621,8 @@ public class CockroachDialect extends Dialect {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getNativeIdentifierGeneratorStrategy() {
|
public GenerationType getNativeValueGenerationStrategy() {
|
||||||
return "sequence";
|
return GenerationType.SEQUENCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -196,6 +196,7 @@ import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
|
import jakarta.persistence.GenerationType;
|
||||||
import jakarta.persistence.TemporalType;
|
import jakarta.persistence.TemporalType;
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
|
@ -2045,11 +2046,21 @@ public abstract class Dialect implements ConversionContext, TypeContributor, Fun
|
||||||
* {@code "native"} is specified in {@code hbm.xml}.
|
* {@code "native"} is specified in {@code hbm.xml}.
|
||||||
*
|
*
|
||||||
* @return The name identifying the native generator strategy.
|
* @return The name identifying the native generator strategy.
|
||||||
|
*
|
||||||
|
* @deprecated Use {@linkplain #getNativeValueGenerationStrategy()} instead
|
||||||
*/
|
*/
|
||||||
|
@Deprecated(since = "7.0", forRemoval = true)
|
||||||
public String getNativeIdentifierGeneratorStrategy() {
|
public String getNativeIdentifierGeneratorStrategy() {
|
||||||
|
return getNativeValueGenerationStrategy().name().toLowerCase( Locale.ROOT );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The native type of generation supported by this Dialect.
|
||||||
|
*/
|
||||||
|
public GenerationType getNativeValueGenerationStrategy() {
|
||||||
return getIdentityColumnSupport().supportsIdentityColumns()
|
return getIdentityColumnSupport().supportsIdentityColumns()
|
||||||
? "identity"
|
? GenerationType.IDENTITY
|
||||||
: "sequence";
|
: GenerationType.SEQUENCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// IDENTITY support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// IDENTITY support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
|
@ -87,6 +87,7 @@ import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||||
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
|
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
|
||||||
import org.hibernate.type.spi.TypeConfiguration;
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
|
import jakarta.persistence.GenerationType;
|
||||||
import jakarta.persistence.TemporalType;
|
import jakarta.persistence.TemporalType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -349,8 +350,8 @@ public class DialectDelegateWrapper extends Dialect {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getNativeIdentifierGeneratorStrategy() {
|
public GenerationType getNativeValueGenerationStrategy() {
|
||||||
return wrapped.getNativeIdentifierGeneratorStrategy();
|
return wrapped.getNativeValueGenerationStrategy();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -100,6 +100,7 @@ import org.hibernate.type.descriptor.sql.internal.NamedNativeOrdinalEnumDdlTypeI
|
||||||
import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry;
|
import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry;
|
||||||
import org.hibernate.type.spi.TypeConfiguration;
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
|
import jakarta.persistence.GenerationType;
|
||||||
import jakarta.persistence.TemporalType;
|
import jakarta.persistence.TemporalType;
|
||||||
|
|
||||||
import static java.util.regex.Pattern.CASE_INSENSITIVE;
|
import static java.util.regex.Pattern.CASE_INSENSITIVE;
|
||||||
|
@ -1045,8 +1046,8 @@ public class OracleDialect extends Dialect {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getNativeIdentifierGeneratorStrategy() {
|
public GenerationType getNativeValueGenerationStrategy() {
|
||||||
return "sequence";
|
return GenerationType.SEQUENCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// features which change between 8i, 9i, and 10g ~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// features which change between 8i, 9i, and 10g ~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
|
@ -95,6 +95,7 @@ import org.hibernate.type.descriptor.sql.internal.Scale6IntervalSecondDdlType;
|
||||||
import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry;
|
import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry;
|
||||||
import org.hibernate.type.spi.TypeConfiguration;
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
|
import jakarta.persistence.GenerationType;
|
||||||
import jakarta.persistence.TemporalType;
|
import jakarta.persistence.TemporalType;
|
||||||
|
|
||||||
import static org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtractor.extractUsingTemplate;
|
import static org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtractor.extractUsingTemplate;
|
||||||
|
@ -856,8 +857,8 @@ public class PostgreSQLDialect extends Dialect {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getNativeIdentifierGeneratorStrategy() {
|
public GenerationType getNativeValueGenerationStrategy() {
|
||||||
return "sequence";
|
return GenerationType.SEQUENCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -0,0 +1,181 @@
|
||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
* Copyright Red Hat Inc. and Hibernate Authors
|
||||||
|
*/
|
||||||
|
package org.hibernate.id;
|
||||||
|
|
||||||
|
import java.lang.reflect.Member;
|
||||||
|
import java.util.EnumSet;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import org.hibernate.boot.model.internal.GeneratorParameters;
|
||||||
|
import org.hibernate.boot.model.relational.Database;
|
||||||
|
import org.hibernate.boot.model.relational.ExportableProducer;
|
||||||
|
import org.hibernate.boot.model.relational.SqlStringGenerationContext;
|
||||||
|
import org.hibernate.boot.models.annotations.internal.UuidGeneratorAnnotation;
|
||||||
|
import org.hibernate.dialect.Dialect;
|
||||||
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
|
import org.hibernate.generator.AnnotationBasedGenerator;
|
||||||
|
import org.hibernate.generator.BeforeExecutionGenerator;
|
||||||
|
import org.hibernate.generator.EventType;
|
||||||
|
import org.hibernate.generator.Generator;
|
||||||
|
import org.hibernate.generator.GeneratorCreationContext;
|
||||||
|
import org.hibernate.generator.OnExecutionGenerator;
|
||||||
|
import org.hibernate.id.enhanced.SequenceStyleGenerator;
|
||||||
|
import org.hibernate.id.enhanced.TableGenerator;
|
||||||
|
import org.hibernate.id.insert.InsertGeneratedIdentifierDelegate;
|
||||||
|
import org.hibernate.id.uuid.UuidGenerator;
|
||||||
|
import org.hibernate.mapping.SimpleValue;
|
||||||
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
|
|
||||||
|
import jakarta.persistence.GenerationType;
|
||||||
|
import jakarta.persistence.SequenceGenerator;
|
||||||
|
|
||||||
|
import static org.hibernate.id.IdentifierGenerator.GENERATOR_NAME;
|
||||||
|
import static org.hibernate.id.OptimizableGenerator.INCREMENT_PARAM;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generator that picks a strategy based on the {@linkplain Dialect#getNativeValueGenerationStrategy() dialect}.
|
||||||
|
*
|
||||||
|
* @see org.hibernate.annotations.NativeGenerator
|
||||||
|
* @since 7.0
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class NativeGenerator
|
||||||
|
implements OnExecutionGenerator, BeforeExecutionGenerator, Configurable, ExportableProducer, AnnotationBasedGenerator<org.hibernate.annotations.NativeGenerator> {
|
||||||
|
private GenerationType generationType;
|
||||||
|
private org.hibernate.annotations.NativeGenerator annotation;
|
||||||
|
private Generator dialectNativeGenerator;
|
||||||
|
|
||||||
|
public GenerationType getGenerationType() {
|
||||||
|
return generationType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EnumSet<EventType> getEventTypes() {
|
||||||
|
return dialectNativeGenerator.getEventTypes();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean generatedOnExecution() {
|
||||||
|
return dialectNativeGenerator.generatedOnExecution();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize(
|
||||||
|
org.hibernate.annotations.NativeGenerator annotation,
|
||||||
|
Member member,
|
||||||
|
GeneratorCreationContext context) {
|
||||||
|
this.annotation = annotation;
|
||||||
|
|
||||||
|
generationType = context.getDatabase()
|
||||||
|
.getDialect()
|
||||||
|
.getNativeValueGenerationStrategy();
|
||||||
|
switch ( generationType ) {
|
||||||
|
case TABLE: {
|
||||||
|
dialectNativeGenerator = new TableGenerator();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case IDENTITY: {
|
||||||
|
dialectNativeGenerator = new IdentityGenerator();
|
||||||
|
context.getProperty().getValue().getColumns().get( 0 ).setIdentity( true );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case UUID: {
|
||||||
|
dialectNativeGenerator = new UuidGenerator( new UuidGeneratorAnnotation( null ), member );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
assert generationType == GenerationType.AUTO || generationType == GenerationType.SEQUENCE;
|
||||||
|
dialectNativeGenerator = new SequenceStyleGenerator();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void configure(GeneratorCreationContext creationContext, Properties parameters) {
|
||||||
|
if ( dialectNativeGenerator instanceof SequenceStyleGenerator sequenceStyleGenerator ) {
|
||||||
|
applyProperties( parameters, annotation.sequenceForm(), creationContext );
|
||||||
|
sequenceStyleGenerator.configure( creationContext, parameters );
|
||||||
|
}
|
||||||
|
else if ( dialectNativeGenerator instanceof TableGenerator tableGenerator ) {
|
||||||
|
applyProperties( parameters, annotation.tableForm(), creationContext );
|
||||||
|
tableGenerator.configure( creationContext, parameters );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerExportables(Database database) {
|
||||||
|
if ( dialectNativeGenerator instanceof ExportableProducer exportableProducer ) {
|
||||||
|
exportableProducer.registerExportables(database);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize(SqlStringGenerationContext context) {
|
||||||
|
if ( dialectNativeGenerator instanceof Configurable configurable ) {
|
||||||
|
configurable.initialize(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object generate(SharedSessionContractImplementor session, Object owner, Object currentValue, EventType eventType) {
|
||||||
|
return ((BeforeExecutionGenerator) dialectNativeGenerator).generate(session, owner, currentValue, eventType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean referenceColumnsInSql(Dialect dialect) {
|
||||||
|
return ((OnExecutionGenerator) dialectNativeGenerator).referenceColumnsInSql(dialect);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean writePropertyValue() {
|
||||||
|
return ((OnExecutionGenerator) dialectNativeGenerator).writePropertyValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getReferencedColumnValues(Dialect dialect) {
|
||||||
|
return ((OnExecutionGenerator) dialectNativeGenerator).getReferencedColumnValues(dialect);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InsertGeneratedIdentifierDelegate getGeneratedIdentifierDelegate(EntityPersister persister) {
|
||||||
|
return ((OnExecutionGenerator) dialectNativeGenerator).getGeneratedIdentifierDelegate(persister);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void applyProperties(
|
||||||
|
Properties properties,
|
||||||
|
SequenceGenerator sequenceAnnotation,
|
||||||
|
GeneratorCreationContext creationContext) {
|
||||||
|
//noinspection unchecked,rawtypes
|
||||||
|
final Map<String,Object> mapRef = (Map) properties;
|
||||||
|
mapRef.put( GENERATOR_NAME, sequenceAnnotation.name() );
|
||||||
|
applyCommonConfiguration( mapRef, creationContext );
|
||||||
|
SequenceStyleGenerator.applyConfiguration( sequenceAnnotation, mapRef::put );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void applyProperties(
|
||||||
|
Properties properties,
|
||||||
|
jakarta.persistence.TableGenerator tableGenerator,
|
||||||
|
GeneratorCreationContext creationContext) {
|
||||||
|
//noinspection unchecked,rawtypes
|
||||||
|
final Map<String,Object> mapRef = (Map) properties;
|
||||||
|
mapRef.put( GENERATOR_NAME, tableGenerator.name() );
|
||||||
|
applyCommonConfiguration( mapRef, creationContext );
|
||||||
|
TableGenerator.applyConfiguration( tableGenerator, mapRef::put );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void applyCommonConfiguration(
|
||||||
|
Map<String, Object> mapRef,
|
||||||
|
GeneratorCreationContext context) {
|
||||||
|
GeneratorParameters.collectParameters(
|
||||||
|
(SimpleValue) context.getProperty().getValue(),
|
||||||
|
context.getDatabase().getDialect(),
|
||||||
|
context.getRootClass(),
|
||||||
|
mapRef::put
|
||||||
|
);
|
||||||
|
mapRef.put( INCREMENT_PARAM, 1 );
|
||||||
|
}
|
||||||
|
}
|
|
@ -27,6 +27,7 @@ import org.hibernate.id.enhanced.SequenceStyleGenerator;
|
||||||
import org.hibernate.id.enhanced.StandardNamingStrategy;
|
import org.hibernate.id.enhanced.StandardNamingStrategy;
|
||||||
import org.hibernate.mapping.KeyValue;
|
import org.hibernate.mapping.KeyValue;
|
||||||
import org.hibernate.mapping.PersistentClass;
|
import org.hibernate.mapping.PersistentClass;
|
||||||
|
import org.hibernate.orm.test.idgen.n_ative.GeneratorSettingsImpl;
|
||||||
import org.hibernate.service.ServiceRegistry;
|
import org.hibernate.service.ServiceRegistry;
|
||||||
|
|
||||||
import org.hibernate.testing.orm.junit.BaseUnitTest;
|
import org.hibernate.testing.orm.junit.BaseUnitTest;
|
||||||
|
@ -129,7 +130,7 @@ public class SequenceNamingStrategyTest {
|
||||||
assertThat( sequence ).isNotNull();
|
assertThat( sequence ).isNotNull();
|
||||||
|
|
||||||
final PersistentClass entityBinding = metadata.getEntityBinding( entityType.getName() );
|
final PersistentClass entityBinding = metadata.getEntityBinding( entityType.getName() );
|
||||||
final IdentifierGenerator generator = extractGenerator( entityBinding );
|
final IdentifierGenerator generator = extractGenerator( metadata, entityBinding );
|
||||||
assertThat( generator ).isInstanceOf( SequenceStyleGenerator.class );
|
assertThat( generator ).isInstanceOf( SequenceStyleGenerator.class );
|
||||||
final SequenceStyleGenerator sequenceStyleGenerator = (SequenceStyleGenerator) generator;
|
final SequenceStyleGenerator sequenceStyleGenerator = (SequenceStyleGenerator) generator;
|
||||||
assertThat( sequenceStyleGenerator.getDatabaseStructure() ).isInstanceOf( SequenceStructure.class );
|
assertThat( sequenceStyleGenerator.getDatabaseStructure() ).isInstanceOf( SequenceStructure.class );
|
||||||
|
@ -158,9 +159,14 @@ public class SequenceNamingStrategyTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private IdentifierGenerator extractGenerator(PersistentClass entityBinding) {
|
private IdentifierGenerator extractGenerator(MetadataImplementor metadataImplementor, PersistentClass entityBinding) {
|
||||||
KeyValue keyValue = entityBinding.getIdentifier();
|
KeyValue keyValue = entityBinding.getIdentifier();
|
||||||
final Generator generator = keyValue.createGenerator(null, null);
|
final Generator generator = keyValue.createGenerator(
|
||||||
|
metadataImplementor.getDatabase().getDialect(),
|
||||||
|
entityBinding.getRootClass(),
|
||||||
|
entityBinding.getIdentifierProperty(),
|
||||||
|
new GeneratorSettingsImpl( metadataImplementor )
|
||||||
|
);
|
||||||
return generator instanceof IdentifierGenerator ? (IdentifierGenerator) generator : null;
|
return generator instanceof IdentifierGenerator ? (IdentifierGenerator) generator : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ import org.hibernate.id.enhanced.StandardNamingStrategy;
|
||||||
import org.hibernate.mapping.KeyValue;
|
import org.hibernate.mapping.KeyValue;
|
||||||
import org.hibernate.mapping.PersistentClass;
|
import org.hibernate.mapping.PersistentClass;
|
||||||
import org.hibernate.mapping.Table;
|
import org.hibernate.mapping.Table;
|
||||||
|
import org.hibernate.orm.test.idgen.n_ative.GeneratorSettingsImpl;
|
||||||
import org.hibernate.service.ServiceRegistry;
|
import org.hibernate.service.ServiceRegistry;
|
||||||
|
|
||||||
import org.hibernate.testing.orm.junit.BaseUnitTest;
|
import org.hibernate.testing.orm.junit.BaseUnitTest;
|
||||||
|
@ -112,7 +113,7 @@ public class TableNamingStrategyTest {
|
||||||
assertThat( table ).isNotNull();
|
assertThat( table ).isNotNull();
|
||||||
|
|
||||||
final PersistentClass entityBinding = metadata.getEntityBinding( entityType.getName() );
|
final PersistentClass entityBinding = metadata.getEntityBinding( entityType.getName() );
|
||||||
final IdentifierGenerator generator = extractGenerator( entityBinding );
|
final IdentifierGenerator generator = extractGenerator( entityBinding, metadata );
|
||||||
assertThat( generator ).isInstanceOf( org.hibernate.id.enhanced.TableGenerator.class );
|
assertThat( generator ).isInstanceOf( org.hibernate.id.enhanced.TableGenerator.class );
|
||||||
final org.hibernate.id.enhanced.TableGenerator tableGenerator = (org.hibernate.id.enhanced.TableGenerator) generator;
|
final org.hibernate.id.enhanced.TableGenerator tableGenerator = (org.hibernate.id.enhanced.TableGenerator) generator;
|
||||||
assertThat( tableGenerator.getTableName() ).isEqualTo( expectedName );
|
assertThat( tableGenerator.getTableName() ).isEqualTo( expectedName );
|
||||||
|
@ -139,9 +140,14 @@ public class TableNamingStrategyTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private IdentifierGenerator extractGenerator(PersistentClass entityBinding) {
|
private IdentifierGenerator extractGenerator(PersistentClass entityBinding, MetadataImplementor metadata) {
|
||||||
KeyValue keyValue = entityBinding.getIdentifier();
|
KeyValue keyValue = entityBinding.getIdentifier();
|
||||||
final Generator generator = keyValue.createGenerator(null, null);
|
final Generator generator = keyValue.createGenerator(
|
||||||
|
metadata.getDatabase().getDialect(),
|
||||||
|
entityBinding.getRootClass(),
|
||||||
|
entityBinding.getIdentifierProperty(),
|
||||||
|
new GeneratorSettingsImpl( metadata )
|
||||||
|
);
|
||||||
return generator instanceof IdentifierGenerator ? (IdentifierGenerator) generator : null;
|
return generator instanceof IdentifierGenerator ? (IdentifierGenerator) generator : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,8 @@ 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;
|
||||||
import org.hibernate.mapping.Property;
|
import org.hibernate.mapping.Property;
|
||||||
|
import org.hibernate.orm.test.idgen.n_ative.GeneratorSettingsImpl;
|
||||||
|
|
||||||
import org.hibernate.testing.orm.junit.FailureExpectedExtension;
|
import org.hibernate.testing.orm.junit.FailureExpectedExtension;
|
||||||
import org.hibernate.testing.util.ServiceRegistryUtil;
|
import org.hibernate.testing.util.ServiceRegistryUtil;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
@ -85,7 +87,12 @@ public class AutoGenerationTypeTests {
|
||||||
final PersistentClass entityBinding = metadata.getEntityBinding( Entity2.class.getName() );
|
final PersistentClass entityBinding = metadata.getEntityBinding( Entity2.class.getName() );
|
||||||
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(),
|
||||||
|
entityBinding.getIdentifierProperty(),
|
||||||
|
new GeneratorSettingsImpl( metadata )
|
||||||
|
);
|
||||||
final SequenceStyleGenerator idGenerator = (SequenceStyleGenerator) (generator instanceof IdentifierGenerator ? (IdentifierGenerator) generator : null);
|
final SequenceStyleGenerator idGenerator = (SequenceStyleGenerator) (generator instanceof IdentifierGenerator ? (IdentifierGenerator) generator : null);
|
||||||
|
|
||||||
final DatabaseStructure database2Structure = idGenerator.getDatabaseStructure();
|
final DatabaseStructure database2Structure = idGenerator.getDatabaseStructure();
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
* Copyright Red Hat Inc. and Hibernate Authors
|
||||||
|
*/
|
||||||
|
package org.hibernate.orm.test.idgen.n_ative;
|
||||||
|
|
||||||
|
import org.hibernate.boot.Metadata;
|
||||||
|
import org.hibernate.boot.model.relational.Database;
|
||||||
|
import org.hibernate.boot.model.relational.Namespace;
|
||||||
|
import org.hibernate.boot.model.relational.SqlStringGenerationContext;
|
||||||
|
import org.hibernate.mapping.GeneratorSettings;
|
||||||
|
|
||||||
|
import static org.hibernate.boot.model.relational.internal.SqlStringGenerationContextImpl.fromExplicit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class GeneratorSettingsImpl implements GeneratorSettings {
|
||||||
|
private final String defaultCatalog;
|
||||||
|
private final String defaultSchema;
|
||||||
|
private final SqlStringGenerationContext sqlStringGenerationContext;
|
||||||
|
|
||||||
|
public GeneratorSettingsImpl(Metadata domainModel) {
|
||||||
|
final Database database = domainModel.getDatabase();
|
||||||
|
final Namespace defaultNamespace = database.getDefaultNamespace();
|
||||||
|
final Namespace.Name defaultNamespaceName = defaultNamespace.getName();
|
||||||
|
|
||||||
|
defaultCatalog = defaultNamespaceName.getCatalog() == null
|
||||||
|
? ""
|
||||||
|
: defaultNamespaceName.getCatalog().render( database.getDialect() );
|
||||||
|
defaultSchema = defaultNamespaceName.getSchema() == null
|
||||||
|
? ""
|
||||||
|
: defaultNamespaceName.getSchema().render( database.getDialect() );
|
||||||
|
|
||||||
|
sqlStringGenerationContext = fromExplicit(
|
||||||
|
database.getJdbcEnvironment(),
|
||||||
|
database,
|
||||||
|
defaultCatalog,
|
||||||
|
defaultSchema
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDefaultCatalog() {
|
||||||
|
return defaultCatalog;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDefaultSchema() {
|
||||||
|
return defaultSchema;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SqlStringGenerationContext getSqlStringGenerationContext() {
|
||||||
|
return sqlStringGenerationContext;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
* Copyright Red Hat Inc. and Hibernate Authors
|
||||||
|
*/
|
||||||
|
package org.hibernate.orm.test.idgen.n_ative.local;
|
||||||
|
|
||||||
|
|
||||||
|
import org.hibernate.generator.Generator;
|
||||||
|
import org.hibernate.id.NativeGenerator;
|
||||||
|
import org.hibernate.mapping.KeyValue;
|
||||||
|
import org.hibernate.mapping.PersistentClass;
|
||||||
|
import org.hibernate.mapping.Property;
|
||||||
|
import org.hibernate.orm.test.idgen.n_ative.GeneratorSettingsImpl;
|
||||||
|
|
||||||
|
import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
|
import org.hibernate.testing.orm.junit.DomainModelScope;
|
||||||
|
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.Id;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
@SessionFactory
|
||||||
|
@DomainModel(annotatedClasses = NativeGeneratorClassTest.NativeEntity.class)
|
||||||
|
public class NativeGeneratorClassTest {
|
||||||
|
@Test void test(DomainModelScope domainModelScope, SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction(s -> s.persist(new NativeEntity()));
|
||||||
|
|
||||||
|
final PersistentClass entityBinding = domainModelScope.getEntityBinding( NativeEntity.class );
|
||||||
|
final Property idProperty = entityBinding.getIdentifierProperty();
|
||||||
|
final KeyValue identifier = entityBinding.getIdentifier();
|
||||||
|
|
||||||
|
final Generator generator = identifier.createGenerator(
|
||||||
|
domainModelScope.getDomainModel().getDatabase().getDialect(),
|
||||||
|
entityBinding.getRootClass(),
|
||||||
|
idProperty,
|
||||||
|
new GeneratorSettingsImpl( domainModelScope.getDomainModel() )
|
||||||
|
);
|
||||||
|
assertThat( generator ).isInstanceOf( NativeGenerator.class );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@org.hibernate.annotations.NativeGenerator
|
||||||
|
public static class NativeEntity {
|
||||||
|
@Id @GeneratedValue
|
||||||
|
long id;
|
||||||
|
String data;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
* Copyright Red Hat Inc. and Hibernate Authors
|
||||||
|
*/
|
||||||
|
package org.hibernate.orm.test.idgen.n_ative.local;
|
||||||
|
|
||||||
|
|
||||||
|
import org.hibernate.generator.Generator;
|
||||||
|
import org.hibernate.id.NativeGenerator;
|
||||||
|
import org.hibernate.mapping.KeyValue;
|
||||||
|
import org.hibernate.mapping.PersistentClass;
|
||||||
|
import org.hibernate.mapping.Property;
|
||||||
|
import org.hibernate.orm.test.idgen.n_ative.GeneratorSettingsImpl;
|
||||||
|
|
||||||
|
import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
|
import org.hibernate.testing.orm.junit.DomainModelScope;
|
||||||
|
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.Id;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
@SessionFactory
|
||||||
|
@DomainModel(annotatedClasses = NativeGeneratorMemberTest.NativeEntity.class)
|
||||||
|
public class NativeGeneratorMemberTest {
|
||||||
|
@Test void test(DomainModelScope domainModelScope, SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction(s -> s.persist(new NativeEntity()));
|
||||||
|
|
||||||
|
final PersistentClass entityBinding = domainModelScope.getEntityBinding( NativeEntity.class );
|
||||||
|
final Property idProperty = entityBinding.getIdentifierProperty();
|
||||||
|
final KeyValue identifier = entityBinding.getIdentifier();
|
||||||
|
|
||||||
|
final Generator generator = identifier.createGenerator(
|
||||||
|
domainModelScope.getDomainModel().getDatabase().getDialect(),
|
||||||
|
entityBinding.getRootClass(),
|
||||||
|
idProperty,
|
||||||
|
new GeneratorSettingsImpl( domainModelScope.getDomainModel() )
|
||||||
|
);
|
||||||
|
assertThat( generator ).isInstanceOf( NativeGenerator.class );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
public static class NativeEntity {
|
||||||
|
@Id @GeneratedValue
|
||||||
|
@org.hibernate.annotations.NativeGenerator
|
||||||
|
long id;
|
||||||
|
String data;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
* Copyright Red Hat Inc. and Hibernate Authors
|
||||||
|
*/
|
||||||
|
package org.hibernate.orm.test.idgen.n_ative.pkg;
|
||||||
|
|
||||||
|
|
||||||
|
import org.hibernate.generator.Generator;
|
||||||
|
import org.hibernate.id.NativeGenerator;
|
||||||
|
import org.hibernate.mapping.KeyValue;
|
||||||
|
import org.hibernate.mapping.PersistentClass;
|
||||||
|
import org.hibernate.mapping.Property;
|
||||||
|
import org.hibernate.orm.test.idgen.n_ative.GeneratorSettingsImpl;
|
||||||
|
|
||||||
|
import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
|
import org.hibernate.testing.orm.junit.DomainModelScope;
|
||||||
|
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.Id;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
@SessionFactory
|
||||||
|
@DomainModel(annotatedClasses = NativeGeneratorPackageTest.NativeEntity.class)
|
||||||
|
public class NativeGeneratorPackageTest {
|
||||||
|
@Test void test(DomainModelScope domainModelScope, SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction(s -> s.persist(new NativeEntity()));
|
||||||
|
|
||||||
|
final PersistentClass entityBinding = domainModelScope.getEntityBinding( NativeEntity.class );
|
||||||
|
final Property idProperty = entityBinding.getIdentifierProperty();
|
||||||
|
final KeyValue identifier = entityBinding.getIdentifier();
|
||||||
|
final Generator generator = identifier.createGenerator(
|
||||||
|
domainModelScope.getDomainModel().getDatabase().getDialect(),
|
||||||
|
entityBinding.getRootClass(),
|
||||||
|
idProperty,
|
||||||
|
new GeneratorSettingsImpl( domainModelScope.getDomainModel() )
|
||||||
|
);
|
||||||
|
assertThat( generator ).isInstanceOf( NativeGenerator.class );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
public static class NativeEntity {
|
||||||
|
@Id @GeneratedValue
|
||||||
|
long id;
|
||||||
|
String data;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
@org.hibernate.annotations.NativeGenerator
|
||||||
|
package org.hibernate.orm.test.idgen.n_ative.pkg;
|
|
@ -1,102 +0,0 @@
|
||||||
/*
|
|
||||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
|
||||||
* Copyright Red Hat Inc. and Hibernate Authors
|
|
||||||
*/
|
|
||||||
package org.hibernate.orm.test.idgen.userdefined;
|
|
||||||
|
|
||||||
import org.hibernate.boot.model.relational.Database;
|
|
||||||
import org.hibernate.boot.model.relational.ExportableProducer;
|
|
||||||
import org.hibernate.boot.model.relational.SqlStringGenerationContext;
|
|
||||||
import org.hibernate.dialect.Dialect;
|
|
||||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
|
||||||
import org.hibernate.generator.BeforeExecutionGenerator;
|
|
||||||
import org.hibernate.generator.EventType;
|
|
||||||
import org.hibernate.generator.Generator;
|
|
||||||
import org.hibernate.generator.GeneratorCreationContext;
|
|
||||||
import org.hibernate.generator.OnExecutionGenerator;
|
|
||||||
import org.hibernate.id.Configurable;
|
|
||||||
import org.hibernate.id.IdentityGenerator;
|
|
||||||
import org.hibernate.id.enhanced.SequenceStyleGenerator;
|
|
||||||
import org.hibernate.id.insert.InsertGeneratedIdentifierDelegate;
|
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
|
||||||
|
|
||||||
import java.lang.reflect.Member;
|
|
||||||
import java.util.EnumSet;
|
|
||||||
import java.util.Properties;
|
|
||||||
|
|
||||||
public class NativeGenerator
|
|
||||||
implements OnExecutionGenerator, BeforeExecutionGenerator, Configurable, ExportableProducer {
|
|
||||||
|
|
||||||
private final Generator generator;
|
|
||||||
|
|
||||||
public NativeGenerator(NativeId nativeId, Member member, GeneratorCreationContext creationContext) {
|
|
||||||
final String strategy = creationContext.getDatabase().getDialect().getNativeIdentifierGeneratorStrategy();
|
|
||||||
switch (strategy) {
|
|
||||||
case "sequence":
|
|
||||||
generator = new SequenceStyleGenerator();
|
|
||||||
break;
|
|
||||||
case "identity":
|
|
||||||
creationContext.getProperty().getValue().getColumns().get(0).setIdentity(true);
|
|
||||||
generator = new IdentityGenerator();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new IllegalArgumentException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public EnumSet<EventType> getEventTypes() {
|
|
||||||
return generator.getEventTypes();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean generatedOnExecution() {
|
|
||||||
return generator.generatedOnExecution();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void configure(GeneratorCreationContext creationContext, Properties parameters) {
|
|
||||||
if ( generator instanceof Configurable ) {
|
|
||||||
((Configurable) generator).configure( creationContext, parameters );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void registerExportables(Database database) {
|
|
||||||
if ( generator instanceof ExportableProducer exportableProducer ) {
|
|
||||||
exportableProducer.registerExportables(database);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void initialize(SqlStringGenerationContext context) {
|
|
||||||
if ( generator instanceof Configurable configurable ) {
|
|
||||||
configurable.initialize(context);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object generate(SharedSessionContractImplementor session, Object owner, Object currentValue, EventType eventType) {
|
|
||||||
return ((BeforeExecutionGenerator) generator).generate(session, owner, currentValue, eventType);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean referenceColumnsInSql(Dialect dialect) {
|
|
||||||
return ((OnExecutionGenerator) generator).referenceColumnsInSql(dialect);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean writePropertyValue() {
|
|
||||||
return ((OnExecutionGenerator) generator).writePropertyValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String[] getReferencedColumnValues(Dialect dialect) {
|
|
||||||
return ((OnExecutionGenerator) generator).getReferencedColumnValues(dialect);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public InsertGeneratedIdentifierDelegate getGeneratedIdentifierDelegate(EntityPersister persister) {
|
|
||||||
return ((OnExecutionGenerator) generator).getGeneratedIdentifierDelegate(persister);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
/*
|
|
||||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
|
||||||
* Copyright Red Hat Inc. and Hibernate Authors
|
|
||||||
*/
|
|
||||||
package org.hibernate.orm.test.idgen.userdefined;
|
|
||||||
|
|
||||||
import jakarta.persistence.Entity;
|
|
||||||
import jakarta.persistence.Id;
|
|
||||||
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;
|
|
||||||
|
|
||||||
@SessionFactory
|
|
||||||
@DomainModel(annotatedClasses = NativeGeneratorTest.NativeEntity.class)
|
|
||||||
public class NativeGeneratorTest {
|
|
||||||
@Test void test(SessionFactoryScope scope) {
|
|
||||||
scope.inTransaction(s -> s.persist(new NativeEntity()));
|
|
||||||
}
|
|
||||||
@Entity
|
|
||||||
public static class NativeEntity {
|
|
||||||
@Id @NativeId
|
|
||||||
long id;
|
|
||||||
String data;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
/*
|
|
||||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
|
||||||
* Copyright Red Hat Inc. and Hibernate Authors
|
|
||||||
*/
|
|
||||||
package org.hibernate.orm.test.idgen.userdefined;
|
|
||||||
|
|
||||||
import org.hibernate.annotations.IdGeneratorType;
|
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
|
||||||
import java.lang.annotation.Retention;
|
|
||||||
import java.lang.annotation.RetentionPolicy;
|
|
||||||
import java.lang.annotation.Target;
|
|
||||||
|
|
||||||
@Target(ElementType.FIELD)
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
@IdGeneratorType(NativeGenerator.class)
|
|
||||||
public @interface NativeId {
|
|
||||||
}
|
|
Loading…
Reference in New Issue