HHH-18620 - Add @NativeGenerator

This commit is contained in:
Steve Ebersole 2024-10-22 14:38:51 -05:00
parent 3e0568a50e
commit f9d36118ce
5 changed files with 149 additions and 90 deletions

View File

@ -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();
}

View File

@ -438,6 +438,10 @@ public interface HibernateAnnotations {
Nationalized.class,
NationalizedAnnotation.class
);
OrmAnnotationDescriptor<NativeGenerator, NativeGeneratorAnnotation> NATIVE_GENERATOR = new OrmAnnotationDescriptor<>(
NativeGenerator.class,
NativeGeneratorAnnotation.class
);
OrmAnnotationDescriptor<NaturalId, NaturalIdAnnotation> NATURAL_ID = new OrmAnnotationDescriptor<>(
NaturalId.class,
NaturalIdAnnotation.class

View File

@ -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<String, Object> 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<? extends Annotation> annotationType() {
return NativeGenerator.class;
}
}

View File

@ -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

View File

@ -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: {