mirror of
https://github.com/hibernate/hibernate-orm
synced 2025-02-17 00:24:57 +00:00
HHH-14497 - Drop legacy id-generator settings;
HHH-14718 - Drop deprecated generator implementations; HHH-14959 - Drop IdentifierGeneratorFactory as a Service; HHH-14960 - Add @GeneratorType for better custom generator config
This commit is contained in:
parent
c394261508
commit
ce4f22f400
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* 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.annotations;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
import org.hibernate.id.IdentifierGenerator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Meta-annotation used to mark another annotation as providing configuration
|
||||||
|
* for a custom {@link org.hibernate.id.IdentifierGenerator}.
|
||||||
|
*/
|
||||||
|
@Target( value = ElementType.ANNOTATION_TYPE )
|
||||||
|
@Retention( RetentionPolicy.RUNTIME )
|
||||||
|
public @interface IdGeneratorType {
|
||||||
|
/**
|
||||||
|
* The IdentifierGenerator being configured
|
||||||
|
*/
|
||||||
|
Class<? extends IdentifierGenerator> value();
|
||||||
|
}
|
@ -6,6 +6,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.hibernate.cfg;
|
package org.hibernate.cfg;
|
||||||
|
|
||||||
|
import java.lang.annotation.Annotation;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@ -22,6 +24,7 @@
|
|||||||
import org.hibernate.AnnotationException;
|
import org.hibernate.AnnotationException;
|
||||||
import org.hibernate.AssertionFailure;
|
import org.hibernate.AssertionFailure;
|
||||||
import org.hibernate.FetchMode;
|
import org.hibernate.FetchMode;
|
||||||
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
import org.hibernate.annotations.BatchSize;
|
import org.hibernate.annotations.BatchSize;
|
||||||
import org.hibernate.annotations.Cache;
|
import org.hibernate.annotations.Cache;
|
||||||
@ -46,6 +49,7 @@
|
|||||||
import org.hibernate.annotations.Formula;
|
import org.hibernate.annotations.Formula;
|
||||||
import org.hibernate.annotations.GenericGenerator;
|
import org.hibernate.annotations.GenericGenerator;
|
||||||
import org.hibernate.annotations.GenericGenerators;
|
import org.hibernate.annotations.GenericGenerators;
|
||||||
|
import org.hibernate.annotations.IdGeneratorType;
|
||||||
import org.hibernate.annotations.Index;
|
import org.hibernate.annotations.Index;
|
||||||
import org.hibernate.annotations.JavaTypeRegistration;
|
import org.hibernate.annotations.JavaTypeRegistration;
|
||||||
import org.hibernate.annotations.JavaTypeRegistrations;
|
import org.hibernate.annotations.JavaTypeRegistrations;
|
||||||
@ -100,6 +104,8 @@
|
|||||||
import org.hibernate.cfg.internal.NullableDiscriminatorColumnSecondPass;
|
import org.hibernate.cfg.internal.NullableDiscriminatorColumnSecondPass;
|
||||||
import org.hibernate.engine.OptimisticLockStyle;
|
import org.hibernate.engine.OptimisticLockStyle;
|
||||||
import org.hibernate.engine.spi.FilterDefinition;
|
import org.hibernate.engine.spi.FilterDefinition;
|
||||||
|
import org.hibernate.id.IdentifierGenerator;
|
||||||
|
import org.hibernate.id.factory.spi.CustomIdGeneratorCreationContext;
|
||||||
import org.hibernate.internal.CoreMessageLogger;
|
import org.hibernate.internal.CoreMessageLogger;
|
||||||
import org.hibernate.internal.util.StringHelper;
|
import org.hibernate.internal.util.StringHelper;
|
||||||
import org.hibernate.jpa.event.internal.CallbackDefinitionResolverLegacyImpl;
|
import org.hibernate.jpa.event.internal.CallbackDefinitionResolverLegacyImpl;
|
||||||
@ -2544,46 +2550,75 @@ private static void processId(
|
|||||||
final boolean isComponent = entityXClass.isAnnotationPresent( Embeddable.class )
|
final boolean isComponent = entityXClass.isAnnotationPresent( Embeddable.class )
|
||||||
|| idXProperty.isAnnotationPresent( EmbeddedId.class );
|
|| idXProperty.isAnnotationPresent( EmbeddedId.class );
|
||||||
|
|
||||||
GeneratedValue generatedValue = idXProperty.getAnnotation( GeneratedValue.class );
|
final Annotation generatorAnnotation = HCANNHelper.findContainingAnnotation( idXProperty, IdGeneratorType.class, buildingContext );
|
||||||
String generatorType = generatedValue != null
|
if ( generatorAnnotation != null ) {
|
||||||
? generatorType( generatedValue, buildingContext, entityXClass )
|
final IdGeneratorType idGeneratorType = generatorAnnotation.annotationType().getAnnotation( IdGeneratorType.class );
|
||||||
: "assigned";
|
assert idGeneratorType != null;
|
||||||
String generatorName = generatedValue != null
|
|
||||||
? generatedValue.generator()
|
|
||||||
: BinderHelper.ANNOTATION_STRING_DEFAULT;
|
|
||||||
if ( isComponent ) {
|
|
||||||
//a component must not have any generator
|
|
||||||
generatorType = "assigned";
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( isGlobalGeneratorNameGlobal( buildingContext ) ) {
|
idValue.setCustomIdGeneratorCreator( (context) -> {
|
||||||
buildGenerators( idXProperty, buildingContext );
|
final Class<? extends IdentifierGenerator> generatorClass = idGeneratorType.value();
|
||||||
SecondPass secondPass = new IdGeneratorResolverSecondPass(
|
try {
|
||||||
idValue,
|
return generatorClass
|
||||||
idXProperty,
|
.getConstructor( generatorAnnotation.annotationType(), CustomIdGeneratorCreationContext.class )
|
||||||
generatorType,
|
.newInstance( generatorAnnotation, context );
|
||||||
generatorName,
|
}
|
||||||
buildingContext
|
catch (NoSuchMethodException e) {
|
||||||
);
|
throw new HibernateException(
|
||||||
buildingContext.getMetadataCollector().addSecondPass( secondPass );
|
"Unable to find appropriate constructor for @IdGeneratorType handling : " + generatorClass.getName(),
|
||||||
|
e
|
||||||
|
);
|
||||||
|
}
|
||||||
|
catch (InvocationTargetException | InstantiationException | IllegalAccessException e) {
|
||||||
|
throw new HibernateException(
|
||||||
|
"Unable to invoke constructor for @IdGeneratorType handling : " + generatorClass.getName(),
|
||||||
|
e
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
//clone classGenerator and override with local values
|
GeneratedValue generatedValue = idXProperty.getAnnotation( GeneratedValue.class );
|
||||||
HashMap<String, IdentifierGeneratorDefinition> localGenerators = (HashMap<String, IdentifierGeneratorDefinition>) classGenerators
|
|
||||||
.clone();
|
|
||||||
localGenerators.putAll( buildGenerators( idXProperty, buildingContext ) );
|
|
||||||
BinderHelper.makeIdGenerator(
|
|
||||||
idValue,
|
|
||||||
idXProperty,
|
|
||||||
generatorType,
|
|
||||||
generatorName,
|
|
||||||
buildingContext,
|
|
||||||
localGenerators
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( LOG.isTraceEnabled() ) {
|
String generatorType = generatedValue != null
|
||||||
LOG.tracev( "Bind {0} on {1}", ( isComponent ? "@EmbeddedId" : "@Id" ), inferredData.getPropertyName() );
|
? generatorType( generatedValue, buildingContext, entityXClass )
|
||||||
|
: "assigned";
|
||||||
|
String generatorName = generatedValue != null
|
||||||
|
? generatedValue.generator()
|
||||||
|
: BinderHelper.ANNOTATION_STRING_DEFAULT;
|
||||||
|
if ( isComponent ) {
|
||||||
|
//a component must not have any generator
|
||||||
|
generatorType = "assigned";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( isGlobalGeneratorNameGlobal( buildingContext ) ) {
|
||||||
|
buildGenerators( idXProperty, buildingContext );
|
||||||
|
SecondPass secondPass = new IdGeneratorResolverSecondPass(
|
||||||
|
idValue,
|
||||||
|
idXProperty,
|
||||||
|
generatorType,
|
||||||
|
generatorName,
|
||||||
|
buildingContext
|
||||||
|
);
|
||||||
|
buildingContext.getMetadataCollector().addSecondPass( secondPass );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//clone classGenerator and override with local values
|
||||||
|
HashMap<String, IdentifierGeneratorDefinition> localGenerators = (HashMap<String, IdentifierGeneratorDefinition>) classGenerators
|
||||||
|
.clone();
|
||||||
|
localGenerators.putAll( buildGenerators( idXProperty, buildingContext ) );
|
||||||
|
BinderHelper.makeIdGenerator(
|
||||||
|
idValue,
|
||||||
|
idXProperty,
|
||||||
|
generatorType,
|
||||||
|
generatorName,
|
||||||
|
buildingContext,
|
||||||
|
localGenerators
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( LOG.isTraceEnabled() ) {
|
||||||
|
LOG.tracev( "Bind {0} on {1}", ( isComponent ? "@EmbeddedId" : "@Id" ), inferredData.getPropertyName() );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
import org.hibernate.annotations.common.reflection.XAnnotatedElement;
|
import org.hibernate.annotations.common.reflection.XAnnotatedElement;
|
||||||
import org.hibernate.annotations.common.reflection.XProperty;
|
import org.hibernate.annotations.common.reflection.XProperty;
|
||||||
import org.hibernate.annotations.common.reflection.java.JavaXMember;
|
import org.hibernate.annotations.common.reflection.java.JavaXMember;
|
||||||
|
import org.hibernate.boot.spi.MetadataBuildingContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manage the various fun-ness of dealing with HCANN...
|
* Manage the various fun-ness of dealing with HCANN...
|
||||||
@ -57,7 +58,7 @@ public static Member getUnderlyingMember(final JavaXMember jxProperty) {
|
|||||||
*
|
*
|
||||||
* @implNote Searches only one level deep
|
* @implNote Searches only one level deep
|
||||||
*/
|
*/
|
||||||
static <T extends Annotation> T findAnnotation(XAnnotatedElement xAnnotatedElement, Class<T> annotationType) {
|
public static <T extends Annotation> T findAnnotation(XAnnotatedElement xAnnotatedElement, Class<T> annotationType) {
|
||||||
// first, see if we can find it directly...
|
// first, see if we can find it directly...
|
||||||
final T direct = xAnnotatedElement.getAnnotation( annotationType );
|
final T direct = xAnnotatedElement.getAnnotation( annotationType );
|
||||||
if ( direct != null ) {
|
if ( direct != null ) {
|
||||||
@ -82,4 +83,30 @@ static <T extends Annotation> T findAnnotation(XAnnotatedElement xAnnotatedEleme
|
|||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Locate the annotation, relative to `xAnnotatedElement`, which contains
|
||||||
|
* the passed type of annotation.
|
||||||
|
*
|
||||||
|
* @implNote Searches only one level deep
|
||||||
|
*/
|
||||||
|
public static <A extends Annotation, T extends Annotation> A findContainingAnnotation(
|
||||||
|
XAnnotatedElement xAnnotatedElement,
|
||||||
|
Class<T> annotationType,
|
||||||
|
MetadataBuildingContext context) {
|
||||||
|
// xAnnotatedElement = id-prop
|
||||||
|
|
||||||
|
for ( int i = 0; i < xAnnotatedElement.getAnnotations().length; i++ ) {
|
||||||
|
final Annotation annotation = xAnnotatedElement.getAnnotations()[ i ];
|
||||||
|
// annotation = @Sequence
|
||||||
|
|
||||||
|
final T metaAnn = annotation.annotationType().getAnnotation( annotationType );
|
||||||
|
if ( metaAnn != null ) {
|
||||||
|
//noinspection unchecked
|
||||||
|
return (A) annotation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* 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.id.factory.spi;
|
||||||
|
|
||||||
|
import org.hibernate.Incubating;
|
||||||
|
import org.hibernate.boot.model.relational.Database;
|
||||||
|
import org.hibernate.id.factory.IdentifierGeneratorFactory;
|
||||||
|
import org.hibernate.mapping.RootClass;
|
||||||
|
import org.hibernate.service.ServiceRegistry;
|
||||||
|
|
||||||
|
@Incubating
|
||||||
|
public interface CustomIdGeneratorCreationContext {
|
||||||
|
IdentifierGeneratorFactory getIdentifierGeneratorFactory();
|
||||||
|
Database getDatabase();
|
||||||
|
ServiceRegistry getServiceRegistry();
|
||||||
|
|
||||||
|
String getDefaultCatalog();
|
||||||
|
String getDefaultSchema();
|
||||||
|
|
||||||
|
RootClass getRootClass();
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
/*
|
||||||
|
* 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.mapping;
|
||||||
|
|
||||||
|
import org.hibernate.id.IdentifierGenerator;
|
||||||
|
import org.hibernate.id.factory.spi.CustomIdGeneratorCreationContext;
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface IdentifierGeneratorCreator {
|
||||||
|
IdentifierGenerator createGenerator(CustomIdGeneratorCreationContext context);
|
||||||
|
}
|
@ -16,7 +16,6 @@
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import jakarta.persistence.AttributeConverter;
|
|
||||||
|
|
||||||
import org.hibernate.FetchMode;
|
import org.hibernate.FetchMode;
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
@ -25,6 +24,7 @@
|
|||||||
import org.hibernate.boot.model.convert.internal.ClassBasedConverterDescriptor;
|
import org.hibernate.boot.model.convert.internal.ClassBasedConverterDescriptor;
|
||||||
import org.hibernate.boot.model.convert.spi.ConverterDescriptor;
|
import org.hibernate.boot.model.convert.spi.ConverterDescriptor;
|
||||||
import org.hibernate.boot.model.convert.spi.JpaAttributeConverterCreationContext;
|
import org.hibernate.boot.model.convert.spi.JpaAttributeConverterCreationContext;
|
||||||
|
import org.hibernate.boot.model.relational.Database;
|
||||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||||
import org.hibernate.boot.registry.classloading.spi.ClassLoadingException;
|
import org.hibernate.boot.registry.classloading.spi.ClassLoadingException;
|
||||||
import org.hibernate.boot.spi.InFlightMetadataCollector;
|
import org.hibernate.boot.spi.InFlightMetadataCollector;
|
||||||
@ -33,13 +33,13 @@
|
|||||||
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;
|
||||||
import org.hibernate.engine.config.spi.StandardConverters;
|
|
||||||
import org.hibernate.engine.spi.Mapping;
|
import org.hibernate.engine.spi.Mapping;
|
||||||
import org.hibernate.id.IdentifierGenerator;
|
import org.hibernate.id.IdentifierGenerator;
|
||||||
import org.hibernate.id.IdentityGenerator;
|
import org.hibernate.id.IdentityGenerator;
|
||||||
import org.hibernate.id.OptimizableGenerator;
|
import org.hibernate.id.OptimizableGenerator;
|
||||||
import org.hibernate.id.PersistentIdentifierGenerator;
|
import org.hibernate.id.PersistentIdentifierGenerator;
|
||||||
import org.hibernate.id.factory.IdentifierGeneratorFactory;
|
import org.hibernate.id.factory.IdentifierGeneratorFactory;
|
||||||
|
import org.hibernate.id.factory.spi.CustomIdGeneratorCreationContext;
|
||||||
import org.hibernate.internal.CoreLogging;
|
import org.hibernate.internal.CoreLogging;
|
||||||
import org.hibernate.internal.CoreMessageLogger;
|
import org.hibernate.internal.CoreMessageLogger;
|
||||||
import org.hibernate.internal.util.ReflectHelper;
|
import org.hibernate.internal.util.ReflectHelper;
|
||||||
@ -59,6 +59,8 @@
|
|||||||
import org.hibernate.type.spi.TypeConfiguration;
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
import org.hibernate.usertype.DynamicParameterizedType;
|
import org.hibernate.usertype.DynamicParameterizedType;
|
||||||
|
|
||||||
|
import jakarta.persistence.AttributeConverter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Any value that maps to columns.
|
* Any value that maps to columns.
|
||||||
* @author Gavin King
|
* @author Gavin King
|
||||||
@ -84,6 +86,7 @@ public abstract class SimpleValue implements KeyValue {
|
|||||||
private Properties identifierGeneratorProperties;
|
private Properties identifierGeneratorProperties;
|
||||||
private String identifierGeneratorStrategy = DEFAULT_ID_GEN_STRATEGY;
|
private String identifierGeneratorStrategy = DEFAULT_ID_GEN_STRATEGY;
|
||||||
private String nullValue;
|
private String nullValue;
|
||||||
|
|
||||||
private Table table;
|
private Table table;
|
||||||
private String foreignKeyName;
|
private String foreignKeyName;
|
||||||
private String foreignKeyDefinition;
|
private String foreignKeyDefinition;
|
||||||
@ -288,6 +291,7 @@ public void createForeignKeyOfEntity(String entityName) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private IdentifierGeneratorCreator customIdGeneratorCreator;
|
||||||
private IdentifierGenerator identifierGenerator;
|
private IdentifierGenerator identifierGenerator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -301,6 +305,14 @@ public IdentifierGenerator getIdentifierGenerator() {
|
|||||||
return identifierGenerator;
|
return identifierGenerator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setCustomIdGeneratorCreator(IdentifierGeneratorCreator customIdGeneratorCreator) {
|
||||||
|
this.customIdGeneratorCreator = customIdGeneratorCreator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IdentifierGeneratorCreator getCustomIdGeneratorCreator() {
|
||||||
|
return customIdGeneratorCreator;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IdentifierGenerator createIdentifierGenerator(
|
public IdentifierGenerator createIdentifierGenerator(
|
||||||
IdentifierGeneratorFactory identifierGeneratorFactory,
|
IdentifierGeneratorFactory identifierGeneratorFactory,
|
||||||
@ -316,11 +328,47 @@ public IdentifierGenerator createIdentifierGenerator(
|
|||||||
String defaultCatalog,
|
String defaultCatalog,
|
||||||
String defaultSchema,
|
String defaultSchema,
|
||||||
RootClass rootClass) throws MappingException {
|
RootClass rootClass) throws MappingException {
|
||||||
|
|
||||||
if ( identifierGenerator != null ) {
|
if ( identifierGenerator != null ) {
|
||||||
return identifierGenerator;
|
return identifierGenerator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( customIdGeneratorCreator != null ) {
|
||||||
|
final CustomIdGeneratorCreationContext creationContext = new CustomIdGeneratorCreationContext() {
|
||||||
|
@Override
|
||||||
|
public IdentifierGeneratorFactory getIdentifierGeneratorFactory() {
|
||||||
|
return identifierGeneratorFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Database getDatabase() {
|
||||||
|
return buildingContext.getMetadataCollector().getDatabase();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ServiceRegistry getServiceRegistry() {
|
||||||
|
return buildingContext.getBootstrapContext().getServiceRegistry();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDefaultCatalog() {
|
||||||
|
return defaultCatalog;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDefaultSchema() {
|
||||||
|
return defaultSchema;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RootClass getRootClass() {
|
||||||
|
return rootClass;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
identifierGenerator = customIdGeneratorCreator.createGenerator( creationContext );
|
||||||
|
return identifierGenerator;
|
||||||
|
}
|
||||||
|
|
||||||
final Properties params = new Properties();
|
final Properties params = new Properties();
|
||||||
|
|
||||||
// This is for backwards compatibility only;
|
// This is for backwards compatibility only;
|
||||||
@ -407,14 +455,6 @@ public FetchMode getFetchMode() {
|
|||||||
return FetchMode.SELECT;
|
return FetchMode.SELECT;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Properties getIdentifierGeneratorProperties() {
|
|
||||||
return identifierGeneratorProperties;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getNullValue() {
|
|
||||||
return nullValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Table getTable() {
|
public Table getTable() {
|
||||||
return table;
|
return table;
|
||||||
}
|
}
|
||||||
@ -426,11 +466,23 @@ public Table getTable() {
|
|||||||
public String getIdentifierGeneratorStrategy() {
|
public String getIdentifierGeneratorStrategy() {
|
||||||
return identifierGeneratorStrategy;
|
return identifierGeneratorStrategy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the identifierGeneratorStrategy.
|
||||||
|
* @param identifierGeneratorStrategy The identifierGeneratorStrategy to set
|
||||||
|
*/
|
||||||
|
public void setIdentifierGeneratorStrategy(String identifierGeneratorStrategy) {
|
||||||
|
this.identifierGeneratorStrategy = identifierGeneratorStrategy;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isIdentityColumn(IdentifierGeneratorFactory identifierGeneratorFactory, Dialect dialect) {
|
public boolean isIdentityColumn(IdentifierGeneratorFactory identifierGeneratorFactory, Dialect dialect) {
|
||||||
return IdentityGenerator.class.isAssignableFrom(identifierGeneratorFactory.getIdentifierGeneratorClass( identifierGeneratorStrategy ));
|
return IdentityGenerator.class.isAssignableFrom(identifierGeneratorFactory.getIdentifierGeneratorClass( identifierGeneratorStrategy ));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Properties getIdentifierGeneratorProperties() {
|
||||||
|
return identifierGeneratorProperties;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the identifierGeneratorProperties.
|
* Sets the identifierGeneratorProperties.
|
||||||
* @param identifierGeneratorProperties The identifierGeneratorProperties to set
|
* @param identifierGeneratorProperties The identifierGeneratorProperties to set
|
||||||
@ -451,12 +503,8 @@ public void setIdentifierGeneratorProperties(Map identifierGeneratorProperties)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public String getNullValue() {
|
||||||
* Sets the identifierGeneratorStrategy.
|
return nullValue;
|
||||||
* @param identifierGeneratorStrategy The identifierGeneratorStrategy to set
|
|
||||||
*/
|
|
||||||
public void setIdentifierGeneratorStrategy(String identifierGeneratorStrategy) {
|
|
||||||
this.identifierGeneratorStrategy = identifierGeneratorStrategy;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||||
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
|
*/
|
||||||
|
package org.hibernate.orm.test.id.custom;
|
||||||
|
|
||||||
|
import org.hibernate.mapping.BasicValue;
|
||||||
|
import org.hibernate.mapping.Property;
|
||||||
|
|
||||||
|
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 static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
@DomainModel( annotatedClasses = TheEntity.class )
|
||||||
|
@SessionFactory
|
||||||
|
public class CustomGeneratorTests {
|
||||||
|
@Test
|
||||||
|
public void verifyModel(DomainModelScope scope) {
|
||||||
|
scope.withHierarchy( TheEntity.class, (descriptor) -> {
|
||||||
|
final Property idProperty = descriptor.getIdentifierProperty();
|
||||||
|
final BasicValue value = (BasicValue) idProperty.getValue();
|
||||||
|
|
||||||
|
assertThat( value.getCustomIdGeneratorCreator() ).isNotNull();
|
||||||
|
|
||||||
|
final String strategy = value.getIdentifierGeneratorStrategy();
|
||||||
|
assertThat( strategy ).isEqualTo( "assigned" );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void basicUseTest(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction( (session) -> {
|
||||||
|
session.persist( new TheEntity( "steve" ) );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||||
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
|
*/
|
||||||
|
package org.hibernate.orm.test.id.custom;
|
||||||
|
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
import org.hibernate.annotations.IdGeneratorType;
|
||||||
|
import org.hibernate.id.enhanced.Optimizer;
|
||||||
|
|
||||||
|
import static java.lang.annotation.ElementType.FIELD;
|
||||||
|
import static java.lang.annotation.ElementType.METHOD;
|
||||||
|
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||||
|
|
||||||
|
@IdGeneratorType( SimpleSequenceGenerator.class )
|
||||||
|
@Target({METHOD, FIELD})
|
||||||
|
@Retention(RUNTIME)
|
||||||
|
public @interface Sequence {
|
||||||
|
String name();
|
||||||
|
int startWith() default 1;
|
||||||
|
int incrementBy() default 50;
|
||||||
|
Class<? extends Optimizer> optimizerStrategy() default Optimizer.class;
|
||||||
|
}
|
@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||||
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
|
*/
|
||||||
|
package org.hibernate.orm.test.id.custom;
|
||||||
|
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
import org.hibernate.boot.model.naming.Identifier;
|
||||||
|
import org.hibernate.boot.model.relational.Database;
|
||||||
|
import org.hibernate.engine.jdbc.env.spi.IdentifierHelper;
|
||||||
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
|
import org.hibernate.id.IdentifierGenerator;
|
||||||
|
import org.hibernate.id.factory.spi.CustomIdGeneratorCreationContext;
|
||||||
|
|
||||||
|
public class SimpleSequenceGenerator implements IdentifierGenerator {
|
||||||
|
private final Identifier sequenceName;
|
||||||
|
private final String sqlSelectFrag;
|
||||||
|
|
||||||
|
public SimpleSequenceGenerator(Sequence config, CustomIdGeneratorCreationContext context) {
|
||||||
|
final String name = config.name();
|
||||||
|
|
||||||
|
// ignore the other config for now...
|
||||||
|
|
||||||
|
final Database database = context.getDatabase();
|
||||||
|
final IdentifierHelper identifierHelper = database.getJdbcEnvironment().getIdentifierHelper();
|
||||||
|
|
||||||
|
final org.hibernate.boot.model.relational.Sequence sequence = database.getDefaultNamespace().createSequence(
|
||||||
|
identifierHelper.toIdentifier( name ),
|
||||||
|
(physicalName) -> new org.hibernate.boot.model.relational.Sequence(
|
||||||
|
null,
|
||||||
|
database.getDefaultNamespace().getPhysicalName().getCatalog(),
|
||||||
|
database.getDefaultNamespace().getPhysicalName().getSchema(),
|
||||||
|
physicalName,
|
||||||
|
1,
|
||||||
|
50
|
||||||
|
)
|
||||||
|
);
|
||||||
|
this.sequenceName = sequence.getName().getSequenceName();
|
||||||
|
|
||||||
|
this.sqlSelectFrag = database
|
||||||
|
.getDialect()
|
||||||
|
.getSequenceSupport()
|
||||||
|
.getSequenceNextValString( sequenceName.render( database.getDialect() ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object generate(SharedSessionContractImplementor session, Object object) {
|
||||||
|
try {
|
||||||
|
final PreparedStatement st = session.getJdbcCoordinator().getStatementPreparer().prepareStatement( sqlSelectFrag );
|
||||||
|
try {
|
||||||
|
final ResultSet rs = session.getJdbcCoordinator().getResultSetReturn().extract( st );
|
||||||
|
try {
|
||||||
|
rs.next();
|
||||||
|
return rs.getInt( 1 );
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
try {
|
||||||
|
session.getJdbcCoordinator().getLogicalConnection().getResourceRegistry().release( rs, st );
|
||||||
|
}
|
||||||
|
catch( Throwable ignore ) {
|
||||||
|
// intentionally empty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
session.getJdbcCoordinator().getLogicalConnection().getResourceRegistry().release( st );
|
||||||
|
session.getJdbcCoordinator().afterStatementExecution();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
catch ( SQLException sqle) {
|
||||||
|
throw session.getJdbcServices().getSqlExceptionHelper().convert(
|
||||||
|
sqle,
|
||||||
|
"could not get next sequence value",
|
||||||
|
sqlSelectFrag
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||||
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
|
*/
|
||||||
|
package org.hibernate.orm.test.id.custom;
|
||||||
|
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.Table;
|
||||||
|
import jakarta.persistence.Id;
|
||||||
|
import jakarta.persistence.Basic;
|
||||||
|
|
||||||
|
@Entity(name = "TheEntity")
|
||||||
|
@Table(name = "TheEntity")
|
||||||
|
public class TheEntity {
|
||||||
|
@Id
|
||||||
|
@Sequence( name = "seq1" )
|
||||||
|
public Integer id;
|
||||||
|
@Basic
|
||||||
|
public String name;
|
||||||
|
|
||||||
|
private TheEntity() {
|
||||||
|
// for Hibernate use
|
||||||
|
}
|
||||||
|
|
||||||
|
public TheEntity(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user