Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
import org.hibernate.type.descriptor.jdbc.JdbcType;
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;

import jakarta.persistence.GenerationType;
import jakarta.persistence.TemporalType;

import static org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtractor.extractUsingTemplate;
Expand Down Expand Up @@ -283,10 +284,9 @@ public boolean hasSelfReferentialForeignKeyBug() {
return true;
}


@Override
public String getNativeIdentifierGeneratorStrategy() {
return "identity";
public GenerationType getNativeValueGenerationStrategy() {
return GenerationType.IDENTITY;
}

// IDENTITY support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@

import org.jboss.logging.Logger;

import jakarta.persistence.GenerationType;
import jakarta.persistence.TemporalType;

import static org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtractor.extractUsingTemplate;
Expand Down Expand Up @@ -654,8 +655,8 @@ public boolean requiresParensForTupleDistinctCounts() {
}

@Override
public String getNativeIdentifierGeneratorStrategy() {
return "sequence";
public GenerationType getNativeValueGenerationStrategy() {
return GenerationType.SEQUENCE;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@
import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry;
import org.hibernate.type.spi.TypeConfiguration;

import jakarta.persistence.GenerationType;
import jakarta.persistence.TemporalType;

import static java.util.regex.Pattern.CASE_INSENSITIVE;
Expand Down Expand Up @@ -953,8 +954,8 @@ public AggregateSupport getAggregateSupport() {
}

@Override
public String getNativeIdentifierGeneratorStrategy() {
return "sequence";
public GenerationType getNativeValueGenerationStrategy() {
return GenerationType.SEQUENCE;
}

// features which change between 8i, 9i, and 10g ~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@
import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry;
import org.hibernate.type.spi.TypeConfiguration;

import jakarta.persistence.GenerationType;
import jakarta.persistence.TemporalType;

import static org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtractor.extractUsingTemplate;
Expand Down Expand Up @@ -885,8 +886,8 @@ public boolean supportsCaseInsensitiveLike() {
}

@Override
public String getNativeIdentifierGeneratorStrategy() {
return "sequence";
public GenerationType getNativeValueGenerationStrategy() {
return GenerationType.SEQUENCE;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -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();
}
Original file line number Diff line number Diff line change
@@ -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;
}
}
Loading
Loading