diff --git a/hibernate-core/src/main/java/org/hibernate/annotations/NativeGenerator.java b/hibernate-core/src/main/java/org/hibernate/annotations/NativeGenerator.java index 0ce2d45e25..e90a0ed4fa 100644 --- a/hibernate-core/src/main/java/org/hibernate/annotations/NativeGenerator.java +++ b/hibernate-core/src/main/java/org/hibernate/annotations/NativeGenerator.java @@ -30,6 +30,17 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME; @IdGeneratorType(org.hibernate.id.NativeGenerator.class) @Incubating public @interface NativeGenerator { + /** + * Configures the sequence generation when the dialect reports + * {@linkplain jakarta.persistence.GenerationType#SEQUENCE} as + * its native generator + */ SequenceGenerator sequenceForm() default @SequenceGenerator(); + + /** + * Configures the table generation when the dialect reports + * {@linkplain jakarta.persistence.GenerationType#TABLE} as + * its native generator + */ TableGenerator tableForm() default @TableGenerator(); } diff --git a/hibernate-core/src/main/java/org/hibernate/boot/models/HibernateAnnotations.java b/hibernate-core/src/main/java/org/hibernate/boot/models/HibernateAnnotations.java index 4a2ddfec66..5c2ef4f566 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/models/HibernateAnnotations.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/models/HibernateAnnotations.java @@ -438,6 +438,10 @@ public interface HibernateAnnotations { Nationalized.class, NationalizedAnnotation.class ); + OrmAnnotationDescriptor NATIVE_GENERATOR = new OrmAnnotationDescriptor<>( + NativeGenerator.class, + NativeGeneratorAnnotation.class + ); OrmAnnotationDescriptor NATURAL_ID = new OrmAnnotationDescriptor<>( NaturalId.class, NaturalIdAnnotation.class diff --git a/hibernate-core/src/main/java/org/hibernate/boot/models/annotations/internal/NativeGeneratorAnnotation.java b/hibernate-core/src/main/java/org/hibernate/boot/models/annotations/internal/NativeGeneratorAnnotation.java new file mode 100644 index 0000000000..0939ca4d72 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/boot/models/annotations/internal/NativeGeneratorAnnotation.java @@ -0,0 +1,78 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html. + */ +package org.hibernate.boot.models.annotations.internal; + +import jakarta.persistence.SequenceGenerator; +import jakarta.persistence.TableGenerator; +import org.hibernate.annotations.NativeGenerator; +import org.hibernate.boot.model.internal.GeneratorStrategies; +import org.hibernate.models.spi.SourceModelBuildingContext; + +import java.lang.annotation.Annotation; +import java.util.Map; + +@SuppressWarnings({ "ClassExplicitlyAnnotation", "unused" }) +@jakarta.annotation.Generated("org.hibernate.orm.build.annotations.ClassGeneratorProcessor") +public class NativeGeneratorAnnotation implements NativeGenerator { + private SequenceGenerator sequenceForm; + private TableGenerator tableForm; + + /** + * Used in legacy hbm.xml handling. See {@linkplain GeneratorStrategies#generatorClass} + */ + public NativeGeneratorAnnotation() { + this.sequenceForm = new SequenceGeneratorJpaAnnotation( null ); + this.tableForm = new TableGeneratorJpaAnnotation( null ); + } + + /** + * Used in creating dynamic annotation instances (e.g. from XML) + */ + public NativeGeneratorAnnotation(SourceModelBuildingContext modelContext) { + this.sequenceForm = new SequenceGeneratorJpaAnnotation( modelContext ); + this.tableForm = new TableGeneratorJpaAnnotation( modelContext ); + } + + /** + * Used in creating annotation instances from JDK variant + */ + public NativeGeneratorAnnotation(NativeGenerator annotation, SourceModelBuildingContext modelContext) { + this.sequenceForm = annotation.sequenceForm(); + this.tableForm = annotation.tableForm(); + } + + /** + * Used in creating annotation instances from Jandex variant + */ + public NativeGeneratorAnnotation(Map attributeValues, SourceModelBuildingContext modelContext) { + this.sequenceForm = (SequenceGenerator) attributeValues.get( "sequenceForm" ); + this.tableForm = (TableGenerator) attributeValues.get( "tableForm" ); + } + + @Override + public SequenceGenerator sequenceForm() { + return sequenceForm; + } + + public void sequenceForm(SequenceGenerator sequenceForm) { + this.sequenceForm = sequenceForm; + } + + @Override + public TableGenerator tableForm() { + return tableForm; + } + + public void tableForm(TableGenerator tableForm) { + this.tableForm = tableForm; + } + + @Override + public Class annotationType() { + return NativeGenerator.class; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java index f69b7c18c5..1b5d1c18b7 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java @@ -4,44 +4,9 @@ */ package org.hibernate.dialect; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.Reader; -import java.lang.invoke.MethodHandles; -import java.sql.Blob; -import java.sql.CallableStatement; -import java.sql.Clob; -import java.sql.Connection; -import java.sql.DatabaseMetaData; -import java.sql.NClob; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.ResultSetMetaData; -import java.sql.SQLException; -import java.sql.Timestamp; -import java.sql.Types; -import java.time.Duration; -import java.time.Instant; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.OffsetDateTime; -import java.time.temporal.TemporalAccessor; -import java.util.Calendar; -import java.util.Date; -import java.util.HashSet; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Objects; -import java.util.Properties; -import java.util.Set; -import java.util.TimeZone; -import java.util.UUID; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - +import jakarta.persistence.GenerationType; +import jakarta.persistence.TemporalType; +import org.checkerframework.checker.nullness.qual.Nullable; import org.hibernate.HibernateException; import org.hibernate.Incubating; import org.hibernate.Length; @@ -67,9 +32,9 @@ import org.hibernate.dialect.function.ExtractFunction; import org.hibernate.dialect.function.InsertSubstringOverlayEmulation; import org.hibernate.dialect.function.LocatePositionEmulation; import org.hibernate.dialect.function.LpadRpadPadEmulation; +import org.hibernate.dialect.function.OrdinalFunction; import org.hibernate.dialect.function.SqlFunction; import org.hibernate.dialect.function.TrimFunction; -import org.hibernate.dialect.function.OrdinalFunction; import org.hibernate.dialect.identity.IdentityColumnSupport; import org.hibernate.dialect.identity.IdentityColumnSupportImpl; import org.hibernate.dialect.lock.LockingStrategy; @@ -195,12 +160,45 @@ import org.hibernate.type.descriptor.sql.internal.CapacityDependentDdlType; import org.hibernate.type.descriptor.sql.internal.DdlTypeImpl; import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry; import org.hibernate.type.spi.TypeConfiguration; - import org.jboss.logging.Logger; -import jakarta.persistence.GenerationType; -import jakarta.persistence.TemporalType; -import org.checkerframework.checker.nullness.qual.Nullable; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.lang.invoke.MethodHandles; +import java.sql.Blob; +import java.sql.CallableStatement; +import java.sql.Clob; +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.NClob; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.sql.Timestamp; +import java.sql.Types; +import java.time.Duration; +import java.time.Instant; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.OffsetDateTime; +import java.time.temporal.TemporalAccessor; +import java.util.Calendar; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Objects; +import java.util.Properties; +import java.util.Set; +import java.util.TimeZone; +import java.util.UUID; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import static java.lang.Math.ceil; import static java.lang.Math.log; @@ -209,44 +207,7 @@ import static org.hibernate.cfg.AvailableSettings.STATEMENT_BATCH_SIZE; import static org.hibernate.cfg.AvailableSettings.USE_GET_GENERATED_KEYS; import static org.hibernate.internal.util.StringHelper.splitAtCommas; import static org.hibernate.internal.util.collections.ArrayHelper.EMPTY_STRING_ARRAY; -import static org.hibernate.type.SqlTypes.ARRAY; -import static org.hibernate.type.SqlTypes.BIGINT; -import static org.hibernate.type.SqlTypes.BINARY; -import static org.hibernate.type.SqlTypes.BLOB; -import static org.hibernate.type.SqlTypes.BOOLEAN; -import static org.hibernate.type.SqlTypes.CHAR; -import static org.hibernate.type.SqlTypes.CLOB; -import static org.hibernate.type.SqlTypes.DATE; -import static org.hibernate.type.SqlTypes.DECIMAL; -import static org.hibernate.type.SqlTypes.DOUBLE; -import static org.hibernate.type.SqlTypes.FLOAT; -import static org.hibernate.type.SqlTypes.INTEGER; -import static org.hibernate.type.SqlTypes.LONG32NVARCHAR; -import static org.hibernate.type.SqlTypes.LONG32VARBINARY; -import static org.hibernate.type.SqlTypes.LONG32VARCHAR; -import static org.hibernate.type.SqlTypes.NCHAR; -import static org.hibernate.type.SqlTypes.NCLOB; -import static org.hibernate.type.SqlTypes.NUMERIC; -import static org.hibernate.type.SqlTypes.NVARCHAR; -import static org.hibernate.type.SqlTypes.REAL; -import static org.hibernate.type.SqlTypes.ROWID; -import static org.hibernate.type.SqlTypes.SMALLINT; -import static org.hibernate.type.SqlTypes.TIME; -import static org.hibernate.type.SqlTypes.TIMESTAMP; -import static org.hibernate.type.SqlTypes.TIMESTAMP_UTC; -import static org.hibernate.type.SqlTypes.TIMESTAMP_WITH_TIMEZONE; -import static org.hibernate.type.SqlTypes.TIME_UTC; -import static org.hibernate.type.SqlTypes.TIME_WITH_TIMEZONE; -import static org.hibernate.type.SqlTypes.TINYINT; -import static org.hibernate.type.SqlTypes.VARBINARY; -import static org.hibernate.type.SqlTypes.VARCHAR; -import static org.hibernate.type.SqlTypes.isCharacterType; -import static org.hibernate.type.SqlTypes.isEnumType; -import static org.hibernate.type.SqlTypes.isFloatOrRealOrDouble; -import static org.hibernate.type.SqlTypes.isIntegral; -import static org.hibernate.type.SqlTypes.isNumericOrDecimal; -import static org.hibernate.type.SqlTypes.isVarbinaryType; -import static org.hibernate.type.SqlTypes.isVarcharType; +import static org.hibernate.type.SqlTypes.*; import static org.hibernate.type.descriptor.DateTimeUtils.JDBC_ESCAPE_END; import static org.hibernate.type.descriptor.DateTimeUtils.JDBC_ESCAPE_START_DATE; import static org.hibernate.type.descriptor.DateTimeUtils.JDBC_ESCAPE_START_TIME; @@ -2057,6 +2018,9 @@ public abstract class Dialect implements ConversionContext, TypeContributor, Fun * @return The name identifying the native generator strategy. * * @deprecated Use {@linkplain #getNativeValueGenerationStrategy()} instead + * + * @implNote Only used with {@code hbm.xml} and {@linkplain org.hibernate.annotations.GenericGenerator}, + * both of which have been deprecated */ @Deprecated(since = "7.0", forRemoval = true) public String getNativeIdentifierGeneratorStrategy() { @@ -2065,7 +2029,11 @@ public abstract class Dialect implements ConversionContext, TypeContributor, Fun /** * The native type of generation supported by this Dialect. + * + * @see org.hibernate.annotations.NativeGenerator + * @since 7.0 */ + @Incubating public GenerationType getNativeValueGenerationStrategy() { return getIdentityColumnSupport().supportsIdentityColumns() ? GenerationType.IDENTITY diff --git a/hibernate-core/src/main/java/org/hibernate/id/NativeGenerator.java b/hibernate-core/src/main/java/org/hibernate/id/NativeGenerator.java index 43aaa6eab9..03e5ce16e6 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/NativeGenerator.java +++ b/hibernate-core/src/main/java/org/hibernate/id/NativeGenerator.java @@ -4,16 +4,12 @@ */ package org.hibernate.id; -import java.lang.reflect.Member; -import java.util.EnumSet; -import java.util.Map; -import java.util.Properties; - +import jakarta.persistence.GenerationType; +import jakarta.persistence.SequenceGenerator; 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; @@ -29,8 +25,10 @@ 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 java.lang.reflect.Member; +import java.util.EnumSet; +import java.util.Map; +import java.util.Properties; import static org.hibernate.id.IdentifierGenerator.GENERATOR_NAME; import static org.hibernate.id.OptimizableGenerator.INCREMENT_PARAM; @@ -84,7 +82,7 @@ public class NativeGenerator break; } case UUID: { - dialectNativeGenerator = new UuidGenerator( new UuidGeneratorAnnotation( null ), member ); + dialectNativeGenerator = new UuidGenerator( context.getType().getReturnedClass() ); break; } default: {