HHH-15789 change IdentifierGeneratorFactory to be able to produce plain InMemoryGenerators

this change is sort-of breaky, so I'm not sure about it

cleanups to StandardIdentifierGeneratorFactory

squash
This commit is contained in:
Gavin 2022-12-01 11:03:01 +01:00 committed by Gavin King
parent cced19c7ee
commit a8aab7f5f2
20 changed files with 192 additions and 129 deletions

View File

@ -74,7 +74,8 @@ public @interface GenericGenerator {
*/
String name();
/**
* The type of identifier generator, a class implementing {@link InMemoryGenerator}.
* The type of identifier generator, a class implementing {@link InMemoryGenerator}
* or, more commonly, {@link org.hibernate.id.IdentifierGenerator}.
*
* @since 6.2
*/
@ -83,7 +84,8 @@ public @interface GenericGenerator {
* The type of identifier generator, the name of either:
* <ul>
* <li>a built-in Hibernate id generator, or
* <li>a custom class implementing {@link org.hibernate.id.IdentifierGenerator}.
* <li>a custom class implementing {@link InMemoryGenerator}, or, more commonly,
* {@link org.hibernate.id.IdentifierGenerator}.
* </ul>
*
* @deprecated use {@link #type()} for typesafety

View File

@ -10,7 +10,6 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.hibernate.id.IdentifierGenerator;
import org.hibernate.tuple.InMemoryGenerator;
import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
@ -18,12 +17,12 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* Meta-annotation used to mark another annotation as providing configuration
* for a custom {@link IdentifierGenerator}. This is the best way to work with
* customized identifier generation in Hibernate.
* for a custom {@linkplain InMemoryGenerator identifier generator}. This is
* the best way to work with customized identifier generation in Hibernate.
* <p>
* For example, if we have a custom identifier generator:
* <pre>{@code
* public class CustomSequenceGenerator implements IdentifierGenerator {
* public class CustomSequenceGenerator implements InMemoryGenerator {
* public CustomSequenceGenerator(CustomSequence config, Member annotatedMember,
* CustomIdGeneratorCreationContext context) {
* ...

View File

@ -20,8 +20,8 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* Meta-annotation used to mark another annotation as providing configuration
* for a custom {@linkplain Generator value generation strategy}.
* This is the best way to work with customized value generation in Hibernate.
* for a custom {@linkplain Generator value generation strategy}. This is the
* best way to work with customized value generation in Hibernate.
* <p>
* For example, if we have a custom value generator:
* <pre>{@code

View File

@ -78,7 +78,6 @@ import org.hibernate.cfg.annotations.NamedEntityGraphDefinition;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.spi.FilterDefinition;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.id.IdentifierGenerator;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.collections.CollectionHelper;
@ -2316,7 +2315,7 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector
// It was done this way in the old code too, so no "regression" here; but
// it could be done better
try {
final InMemoryGenerator generator = identifierValueBinding.createIdentifierGenerator(
final InMemoryGenerator generator = identifierValueBinding.createGenerator(
bootstrapContext.getIdentifierGeneratorFactory(),
dialect,
entityBinding

View File

@ -39,8 +39,8 @@ public class Assigned implements StandardGenerator {
}
@Override
public void configure(Type type, Properties params, ServiceRegistry serviceRegistry) throws MappingException {
entityName = params.getProperty( ENTITY_NAME );
public void configure(Type type, Properties parameters, ServiceRegistry serviceRegistry) throws MappingException {
entityName = parameters.getProperty( ENTITY_NAME );
if ( entityName == null ) {
throw new MappingException("no entity name");
}

View File

@ -70,9 +70,9 @@ public class ForeignGenerator implements StandardGenerator {
@Override
public void configure(Type type, Properties params, ServiceRegistry serviceRegistry) throws MappingException {
propertyName = params.getProperty( "property" );
entityName = params.getProperty( ENTITY_NAME );
public void configure(Type type, Properties parameters, ServiceRegistry serviceRegistry) throws MappingException {
propertyName = parameters.getProperty( "property" );
entityName = parameters.getProperty( ENTITY_NAME );
if ( propertyName==null ) {
throw new MappingException( "param named \"property\" is required for foreign id generation strategy" );
}

View File

@ -28,7 +28,7 @@ import static org.hibernate.tuple.GenerationTiming.INSERT;
* <p>
* This interface extends {@code InMemoryGenerator} with some additional
* machinery for {@linkplain #configure configuration}, and for caching
* {@link #initialize(SqlStringGenerationContext) generated SQL}.
* {@linkplain #initialize(SqlStringGenerationContext) generated SQL}.
* <p>
* Any identifier generator, including a generator which directly implements
* {@code InMemoryGenerator}, may also implement {@link ExportableProducer}.
@ -42,11 +42,15 @@ import static org.hibernate.tuple.GenerationTiming.INSERT;
* <li>several "standard" parameters with keys defined as static members of
* this interface: {@value #ENTITY_NAME}, {@value #JPA_ENTITY_NAME},
* {@value #GENERATOR_NAME}, {@value #CONTRIBUTOR_NAME}, along with
* <li>additional parameters supplied by Hibernate to its built-in generators,
* depending on the generator class, and, possibly,
* <li>additional hardcoded parameters supplied by Hibernate to its built-in
* generators, depending on the generator class, and, possibly,
* <li>{@linkplain org.hibernate.annotations.Parameter parameters} specified
* using {@link org.hibernate.annotations.GenericGenerator#parameters()}.
* </ul>
* Instances of {@code IdentifierGenerator} are usually created and configured
* by the {@link org.hibernate.id.factory.IdentifierGeneratorFactory} service.
* It is not usually correct to use an {@code IdentifierGenerator} with the
* {@link org.hibernate.annotations.IdGeneratorType} meta-annotation.
*
* @author Gavin King
*
@ -85,12 +89,12 @@ public interface IdentifierGenerator extends InMemoryGenerator, ExportableProduc
* and before {@link #registerExportables(Database)}.
*
* @param type The id property type descriptor
* @param params param values, keyed by parameter name
* @param parameters param values, keyed by parameter name
* @param serviceRegistry Access to service that may be needed.
* @throws MappingException If configuration fails.
*/
@Override
default void configure(Type type, Properties params, ServiceRegistry serviceRegistry) {
default void configure(Type type, Properties parameters, ServiceRegistry serviceRegistry) {
}
/**

View File

@ -71,31 +71,31 @@ public class IncrementGenerator implements StandardGenerator {
}
@Override
public void configure(Type type, Properties params, ServiceRegistry serviceRegistry) throws MappingException {
public void configure(Type type, Properties parameters, ServiceRegistry serviceRegistry) throws MappingException {
returnClass = type.getReturnedClass();
final JdbcEnvironment jdbcEnvironment = serviceRegistry.getService( JdbcEnvironment.class );
final ObjectNameNormalizer normalizer =
(ObjectNameNormalizer) params.get( PersistentIdentifierGenerator.IDENTIFIER_NORMALIZER );
(ObjectNameNormalizer) parameters.get( PersistentIdentifierGenerator.IDENTIFIER_NORMALIZER );
column = params.getProperty( "column" );
column = parameters.getProperty( "column" );
if ( column == null ) {
column = params.getProperty( PersistentIdentifierGenerator.PK );
column = parameters.getProperty( PersistentIdentifierGenerator.PK );
}
column = normalizer.normalizeIdentifierQuoting( column ).render( jdbcEnvironment.getDialect() );
IdentifierHelper identifierHelper = jdbcEnvironment.getIdentifierHelper();
final String schema = normalizer.toDatabaseIdentifierText(
params.getProperty( PersistentIdentifierGenerator.SCHEMA )
parameters.getProperty( PersistentIdentifierGenerator.SCHEMA )
);
final String catalog = normalizer.toDatabaseIdentifierText(
params.getProperty( PersistentIdentifierGenerator.CATALOG )
parameters.getProperty( PersistentIdentifierGenerator.CATALOG )
);
String tableList = params.getProperty( "tables" );
String tableList = parameters.getProperty( "tables" );
if ( tableList == null ) {
tableList = params.getProperty( PersistentIdentifierGenerator.TABLES );
tableList = parameters.getProperty( PersistentIdentifierGenerator.TABLES );
}
physicalTableNames = new ArrayList<>();
for ( String tableName : StringHelper.split( ", ", tableList ) ) {

View File

@ -42,8 +42,8 @@ public class SelectGenerator extends AbstractPostInsertGenerator {
private String uniqueKeyPropertyName;
@Override
public void configure(Type type, Properties params, ServiceRegistry serviceRegistry) throws MappingException {
uniqueKeyPropertyName = params.getProperty( "key" );
public void configure(Type type, Properties parameters, ServiceRegistry serviceRegistry) throws MappingException {
uniqueKeyPropertyName = parameters.getProperty( "key" );
}
@Override

View File

@ -51,13 +51,13 @@ public class UUIDGenerator implements StandardGenerator {
private UUIDJavaType.ValueTransformer valueTransformer;
@Override
public void configure(Type type, Properties params, ServiceRegistry serviceRegistry) throws MappingException {
public void configure(Type type, Properties parameters, ServiceRegistry serviceRegistry) throws MappingException {
// check first for an explicit strategy instance
strategy = (UUIDGenerationStrategy) params.get( UUID_GEN_STRATEGY );
strategy = (UUIDGenerationStrategy) parameters.get( UUID_GEN_STRATEGY );
if ( strategy == null ) {
// next check for an explicit strategy class
final String strategyClassName = params.getProperty( UUID_GEN_STRATEGY_CLASS );
final String strategyClassName = parameters.getProperty( UUID_GEN_STRATEGY_CLASS );
if ( strategyClassName != null ) {
try {
final ClassLoaderService cls = serviceRegistry.getService( ClassLoaderService.class );

View File

@ -44,8 +44,8 @@ public class UUIDHexGenerator extends AbstractUUIDGenerator {
@Override
public void configure(Type type, Properties params, ServiceRegistry serviceRegistry) throws MappingException {
sep = ConfigurationHelper.getString( "separator", params, "" );
public void configure(Type type, Properties parameters, ServiceRegistry serviceRegistry) throws MappingException {
sep = ConfigurationHelper.getString( "separator", parameters, "" );
}
@Override

View File

@ -180,21 +180,21 @@ public class SequenceStyleGenerator
// Configurable implementation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override
public void configure(Type type, Properties params, ServiceRegistry serviceRegistry) throws MappingException {
public void configure(Type type, Properties parameters, ServiceRegistry serviceRegistry) throws MappingException {
final JdbcEnvironment jdbcEnvironment = serviceRegistry.getService( JdbcEnvironment.class );
final ConfigurationService configurationService = serviceRegistry.getService( ConfigurationService.class );
final Dialect dialect = jdbcEnvironment.getDialect();
this.identifierType = type;
boolean forceTableUse = ConfigurationHelper.getBoolean( FORCE_TBL_PARAM, params, false );
boolean forceTableUse = ConfigurationHelper.getBoolean( FORCE_TBL_PARAM, parameters, false );
final QualifiedName sequenceName = determineSequenceName( params, dialect, jdbcEnvironment, serviceRegistry );
final QualifiedName sequenceName = determineSequenceName(parameters, dialect, jdbcEnvironment, serviceRegistry );
final int initialValue = determineInitialValue( params );
int incrementSize = determineIncrementSize( params );
final int initialValue = determineInitialValue(parameters);
int incrementSize = determineIncrementSize(parameters);
final String optimizationStrategy = determineOptimizationStrategy( params, incrementSize );
final String optimizationStrategy = determineOptimizationStrategy(parameters, incrementSize );
final boolean isPooledOptimizer = OptimizerFactory.isPooledOptimizer( optimizationStrategy );
@ -242,7 +242,7 @@ public class SequenceStyleGenerator
this.databaseStructure = buildDatabaseStructure(
type,
params,
parameters,
jdbcEnvironment,
forceTableUse,
sequenceName,
@ -253,7 +253,7 @@ public class SequenceStyleGenerator
optimizationStrategy,
identifierType.getReturnedClass(),
incrementSize,
ConfigurationHelper.getInt( INITIAL_PARAM, params, -1 )
ConfigurationHelper.getInt( INITIAL_PARAM, parameters, -1 )
);
this.databaseStructure.configure( optimizer );
}

View File

@ -326,29 +326,29 @@ public class TableGenerator implements PersistentIdentifierGenerator {
}
@Override
public void configure(Type type, Properties params, ServiceRegistry serviceRegistry) throws MappingException {
public void configure(Type type, Properties parameters, ServiceRegistry serviceRegistry) throws MappingException {
storeLastUsedValue = serviceRegistry.getService( ConfigurationService.class )
.getSetting( AvailableSettings.TABLE_GENERATOR_STORE_LAST_USED, StandardConverters.BOOLEAN, true );
identifierType = type;
final JdbcEnvironment jdbcEnvironment = serviceRegistry.getService( JdbcEnvironment.class );
qualifiedTableName = determineGeneratorTableName( params, jdbcEnvironment, serviceRegistry );
segmentColumnName = determineSegmentColumnName( params, jdbcEnvironment );
valueColumnName = determineValueColumnName( params, jdbcEnvironment );
qualifiedTableName = determineGeneratorTableName(parameters, jdbcEnvironment, serviceRegistry );
segmentColumnName = determineSegmentColumnName(parameters, jdbcEnvironment );
valueColumnName = determineValueColumnName(parameters, jdbcEnvironment );
segmentValue = determineSegmentValue( params );
segmentValue = determineSegmentValue(parameters);
segmentValueLength = determineSegmentColumnSize( params );
initialValue = determineInitialValue( params );
incrementSize = determineIncrementSize( params );
segmentValueLength = determineSegmentColumnSize(parameters);
initialValue = determineInitialValue(parameters);
incrementSize = determineIncrementSize(parameters);
final String optimizationStrategy = ConfigurationHelper.getString(
OPT_PARAM,
params,
OptimizerFactory.determineImplicitOptimizerName( incrementSize, params )
parameters,
OptimizerFactory.determineImplicitOptimizerName( incrementSize, parameters)
);
int optimizerInitialValue = ConfigurationHelper.getInt( INITIAL_PARAM, params, -1 );
int optimizerInitialValue = ConfigurationHelper.getInt( INITIAL_PARAM, parameters, -1 );
optimizer = OptimizerFactory.buildOptimizer(
optimizationStrategy,
identifierType.getReturnedClass(),
@ -356,7 +356,7 @@ public class TableGenerator implements PersistentIdentifierGenerator {
optimizerInitialValue
);
contributor = params.getProperty( CONTRIBUTOR_NAME );
contributor = parameters.getProperty( CONTRIBUTOR_NAME );
if ( contributor == null ) {
contributor = "orm";
}

View File

@ -8,25 +8,49 @@ package org.hibernate.id.factory;
import java.util.Properties;
import org.hibernate.Incubating;
import org.hibernate.dialect.Dialect;
import org.hibernate.id.IdentifierGenerator;
import org.hibernate.id.factory.spi.GeneratorDefinitionResolver;
import org.hibernate.service.Service;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.tuple.InMemoryGenerator;
import org.hibernate.type.Type;
import org.hibernate.type.descriptor.java.JavaType;
import jakarta.persistence.GenerationType;
/**
* Contract for a {@code factory} of {@link IdentifierGenerator} instances.
* Contract for a factory of {@link IdentifierGenerator} instances. The implementor
* of this service is responsible for providing implementations of the predefined
* built-in id generators, all of which implement {@link IdentifierGenerator}, along
* with any id generator declared using {@link org.hibernate.annotations.GenericGenerator}.
* <p>
* An id generator is identified by either:
* <ul>
* <li>a predefined string-based name (which originated in the old {@code hbm.xml}
* mapping file format),
* <li>the {@link org.hibernate.annotations.GenericGenerator#name name} or the
* the {@link org.hibernate.annotations.GenericGenerator#type type} specified
* by the {@code @GenericGenerator} annotation, or
* <li>a JPA-defined {@link GenerationType}.
* </ul>
* A new generator passed a {@link Properties} object containing parameters via the
* method {@link IdentifierGenerator#configure(Type, Properties, ServiceRegistry)}.
* <p>
* This is part of an older mechanism for instantiating and configuring id generators
* which predates the existence of {@link org.hibernate.tuple.Generator} and the
* {@link org.hibernate.annotations.IdGeneratorType @IdGeneratorType} meta-annotation.
*
* @author Steve Ebersole
*/
@Incubating //this API is currently in flux
public interface IdentifierGeneratorFactory extends Service {
/**
* Create an IdentifierGenerator based on the given details
* Create an {@link IdentifierGenerator} based on the given details.
*/
IdentifierGenerator createIdentifierGenerator(
@Incubating
InMemoryGenerator createIdentifierGenerator(
GenerationType generationType,
String generatedValueGeneratorName,
String generatorName,
@ -39,7 +63,7 @@ public interface IdentifierGeneratorFactory extends Service {
*
* @param strategy The generation strategy.
* @param type The mapping type for the identifier values.
* @param config Any configuration properties given in the generator mapping.
* @param parameters Any parameters properties given in the generator mapping.
*
* @return The appropriate generator instance.
*
@ -47,7 +71,7 @@ public interface IdentifierGeneratorFactory extends Service {
* instead
*/
@Deprecated(since = "6.0")
IdentifierGenerator createIdentifierGenerator(String strategy, Type type, Properties config);
InMemoryGenerator createIdentifierGenerator(String strategy, Type type, Properties parameters);
/**
* Retrieve the class that will be used as the {@link IdentifierGenerator} for the given strategy.
@ -59,7 +83,7 @@ public interface IdentifierGeneratorFactory extends Service {
* {@link #createIdentifierGenerator(GenerationType, String, String, JavaType, Properties, GeneratorDefinitionResolver)}
*/
@Deprecated(since = "6.0")
Class<?> getIdentifierGeneratorClass(String strategy);
Class<? extends InMemoryGenerator> getIdentifierGeneratorClass(String strategy);
/**
* Get the dialect.

View File

@ -20,12 +20,13 @@ import org.hibernate.mapping.Column;
import org.hibernate.mapping.RootClass;
import org.hibernate.mapping.SimpleValue;
import org.hibernate.mapping.Table;
import org.hibernate.tuple.InMemoryGenerator;
import java.util.Properties;
public class IdentifierGeneratorUtil {
public static IdentifierGenerator createLegacyIdentifierGenerator(
public static InMemoryGenerator createLegacyIdentifierGenerator(
SimpleValue simpleValue,
IdentifierGeneratorFactory identifierGeneratorFactory,
Dialect dialect,

View File

@ -7,7 +7,6 @@
package org.hibernate.id.factory.internal;
import java.io.Serializable;
import java.util.Collection;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
@ -18,7 +17,6 @@ import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.boot.registry.classloading.spi.ClassLoadingException;
import org.hibernate.boot.registry.selector.spi.StrategySelector;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.config.spi.ConfigurationService;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
@ -41,22 +39,24 @@ import org.hibernate.id.factory.spi.StandardGenerator;
import org.hibernate.internal.log.DeprecationLogger;
import org.hibernate.jpa.spi.IdentifierGeneratorStrategyProvider;
import org.hibernate.resource.beans.container.spi.BeanContainer;
import org.hibernate.resource.beans.container.spi.ContainedBean;
import org.hibernate.resource.beans.internal.FallbackBeanInstanceProducer;
import org.hibernate.resource.beans.internal.Helper;
import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.tuple.InMemoryGenerator;
import org.hibernate.type.Type;
import org.hibernate.type.descriptor.java.JavaType;
import static org.hibernate.cfg.AvailableSettings.IDENTIFIER_GENERATOR_STRATEGY_PROVIDER;
import static org.hibernate.id.factory.IdGenFactoryLogging.ID_GEN_FAC_LOGGER;
/**
* Basic implementation of {@link org.hibernate.id.factory.IdentifierGeneratorFactory}.
* Basic implementation of {@link org.hibernate.id.factory.IdentifierGeneratorFactory},
* responsible for instantiating the predefined built-in id generators, and generators
* declared using {@link org.hibernate.annotations.GenericGenerator}.
*
* @author Steve Ebersole
*/
@SuppressWarnings( { "deprecation" ,"rawtypes" } )
public class StandardIdentifierGeneratorFactory
implements IdentifierGeneratorFactory, BeanContainer.LifecycleOptions, Serializable {
@ -77,23 +77,32 @@ public class StandardIdentifierGeneratorFactory
}
/**
* Constructs a new factory, explicitly controlling whether to use
* CDI or not
* Constructs a new factory, explicitly controlling whether to use CDI or not
*/
public StandardIdentifierGeneratorFactory(ServiceRegistry serviceRegistry, boolean ignoreBeanContainer) {
this.serviceRegistry = serviceRegistry;
beanContainer = getBeanContainer( serviceRegistry, ignoreBeanContainer );
registerJpaGenerators();
logOverrides();
registerPredefinedGenerators();
registerUsingLegacyContributor();
}
if ( ignoreBeanContainer ) {
private static BeanContainer getBeanContainer(ServiceRegistry serviceRegistry, boolean ignoreBeanContainer) {
if (ignoreBeanContainer) {
ID_GEN_FAC_LOGGER.debug( "Ignoring CDI for resolving IdentifierGenerator instances as extended or delayed CDI support was enabled" );
this.beanContainer = null;
return null;
}
else {
this.beanContainer = serviceRegistry.getService( ManagedBeanRegistry.class ).getBeanContainer();
final BeanContainer beanContainer = serviceRegistry.getService( ManagedBeanRegistry.class ).getBeanContainer();
if ( beanContainer == null ) {
ID_GEN_FAC_LOGGER.debug( "Resolving IdentifierGenerator instances will not use CDI as it was not configured" );
}
return beanContainer;
}
}
private void registerJpaGenerators() {
generatorTypeStrategyMap.put( GenerationType.AUTO, AutoGenerationTypeStrategy.INSTANCE );
generatorTypeStrategyMap.put( GenerationType.SEQUENCE, SequenceGenerationTypeStrategy.INSTANCE );
generatorTypeStrategyMap.put( GenerationType.TABLE, TableGenerationTypeStrategy.INSTANCE );
@ -101,30 +110,31 @@ public class StandardIdentifierGeneratorFactory
try {
generatorTypeStrategyMap.put( GenerationType.valueOf( "UUID" ), UUIDGenerationTypeStrategy.INSTANCE );
}
catch (IllegalArgumentException ex) {
// Ignore
catch (IllegalArgumentException ignore) {
}
}
final ClassLoaderService classLoaderService = serviceRegistry.getService( ClassLoaderService.class );
final Collection<GenerationTypeStrategyRegistration> generationTypeStrategyRegistrations = classLoaderService.loadJavaServices( GenerationTypeStrategyRegistration.class );
generationTypeStrategyRegistrations.forEach( (registration) -> registration.registerStrategies(
(generationType, generationTypeStrategy) -> {
final GenerationTypeStrategy previous = generatorTypeStrategyMap.put(
generationType,
generationTypeStrategy
);
if ( previous != null ) {
ID_GEN_FAC_LOGGER.debugf(
"GenerationTypeStrategyRegistration [%s] overrode previous registration for GenerationType#%s : %s",
registration,
generationType.name(),
previous
);
}
},
serviceRegistry
) );
private void logOverrides() {
serviceRegistry.getService( ClassLoaderService.class )
.loadJavaServices( GenerationTypeStrategyRegistration.class )
.forEach( (registration) -> registration.registerStrategies(
(generationType, generationTypeStrategy) -> {
final GenerationTypeStrategy previous =
generatorTypeStrategyMap.put( generationType, generationTypeStrategy );
if ( previous != null ) {
ID_GEN_FAC_LOGGER.debugf(
"GenerationTypeStrategyRegistration [%s] overrode previous registration for GenerationType#%s : %s",
registration,
generationType.name(),
previous
);
}
},
serviceRegistry
) );
}
private void registerPredefinedGenerators() {
register( "uuid2", UUIDGenerator.class );
// can be done with UuidGenerator + strategy
register( "guid", GUIDGenerator.class );
@ -138,26 +148,30 @@ public class StandardIdentifierGeneratorFactory
register( "foreign", ForeignGenerator.class );
register( "enhanced-sequence", SequenceStyleGenerator.class );
register( "enhanced-table", TableGenerator.class );
}
private void registerUsingLegacyContributor() {
final ConfigurationService configService = serviceRegistry.getService( ConfigurationService.class );
final Object providerSetting = configService.getSettings().get( AvailableSettings.IDENTIFIER_GENERATOR_STRATEGY_PROVIDER );
final Object providerSetting = configService.getSettings().get( IDENTIFIER_GENERATOR_STRATEGY_PROVIDER );
if ( providerSetting != null ) {
DeprecationLogger.DEPRECATION_LOGGER.deprecatedSetting2(
AvailableSettings.IDENTIFIER_GENERATOR_STRATEGY_PROVIDER,
IDENTIFIER_GENERATOR_STRATEGY_PROVIDER,
"supply a org.hibernate.id.factory.spi.GenerationTypeStrategyRegistration Java service"
);
final IdentifierGeneratorStrategyProvider idGeneratorStrategyProvider =
serviceRegistry.getService( StrategySelector.class )
.resolveStrategy( IdentifierGeneratorStrategyProvider.class, providerSetting );
for ( Map.Entry<String,Class<?>> entry : idGeneratorStrategyProvider.getStrategies().entrySet() ) {
register( entry.getKey(), (Class) entry.getValue() );
@SuppressWarnings({"rawtypes", "unchecked"})
Class<? extends IdentifierGenerator> generatorClass = (Class) entry.getValue();
register( entry.getKey(), generatorClass );
}
}
}
private void register(String strategy, Class<? extends IdentifierGenerator> generatorClass) {
ID_GEN_FAC_LOGGER.debugf( "Registering IdentifierGenerator strategy [%s] -> [%s]", strategy, generatorClass.getName() );
final Class previous = legacyGeneratorClassNameMap.put( strategy, generatorClass );
final Class<?> previous = legacyGeneratorClassNameMap.put( strategy, generatorClass );
if ( previous != null && ID_GEN_FAC_LOGGER.isDebugEnabled() ) {
ID_GEN_FAC_LOGGER.debugf( " - overriding [%s]", previous.getName() );
}
@ -185,7 +199,7 @@ public class StandardIdentifierGeneratorFactory
throw new NotYetImplementedFor6Exception( getClass() );
}
@Override
@Override @Deprecated
public Dialect getDialect() {
if ( dialect == null ) {
dialect = serviceRegistry.getService( JdbcEnvironment.class ).getDialect();
@ -194,30 +208,28 @@ public class StandardIdentifierGeneratorFactory
}
@Override
public IdentifierGenerator createIdentifierGenerator(String strategy, Type type, Properties config) {
public InMemoryGenerator createIdentifierGenerator(String strategy, Type type, Properties parameters) {
try {
final Class<? extends IdentifierGenerator> clazz = getIdentifierGeneratorClass( strategy );
final IdentifierGenerator identifierGenerator;
final Class<? extends InMemoryGenerator> clazz = getIdentifierGeneratorClass( strategy );
final InMemoryGenerator identifierGenerator;
if ( beanContainer == null
|| StandardGenerator.class.isAssignableFrom( clazz )
|| legacyGeneratorClassNameMap.containsKey( strategy ) ) {
identifierGenerator = clazz.newInstance();
}
else {
final ContainedBean<? extends IdentifierGenerator> generatorBean = beanContainer.getBean(
clazz,
this,
FallbackBeanInstanceProducer.INSTANCE
);
identifierGenerator = generatorBean.getBeanInstance();
identifierGenerator =
beanContainer.getBean( clazz, this, FallbackBeanInstanceProducer.INSTANCE )
.getBeanInstance();
}
identifierGenerator.configure( type, config, serviceRegistry );
if ( identifierGenerator instanceof IdentifierGenerator ) {
( (IdentifierGenerator) identifierGenerator ).configure( type, parameters, serviceRegistry );
}
return identifierGenerator;
}
catch ( Exception e ) {
final String entityName = config.getProperty( IdentifierGenerator.ENTITY_NAME );
final String entityName = parameters.getProperty( IdentifierGenerator.ENTITY_NAME );
throw new MappingException( String.format( "Could not instantiate id generator [entity-name=%s]", entityName ), e );
}
}
@ -233,7 +245,7 @@ public class StandardIdentifierGeneratorFactory
}
@Override
public Class<? extends IdentifierGenerator> getIdentifierGeneratorClass(String strategy) {
public Class<? extends InMemoryGenerator> getIdentifierGeneratorClass(String strategy) {
if ( "hilo".equals( strategy ) ) {
throw new UnsupportedOperationException( "Support for 'hilo' generator has been removed" );
}
@ -242,16 +254,24 @@ public class StandardIdentifierGeneratorFactory
: strategy;
Class<? extends IdentifierGenerator> generatorClass = legacyGeneratorClassNameMap.get( resolvedStrategy );
if ( generatorClass == null ) {
if ( generatorClass != null ) {
return generatorClass;
}
else {
try {
return serviceRegistry.getService( ClassLoaderService.class ).classForName( resolvedStrategy );
Class<? extends InMemoryGenerator> clazz =
serviceRegistry.getService( ClassLoaderService.class )
.classForName( resolvedStrategy );
if ( !InMemoryGenerator.class.isAssignableFrom( clazz ) ) {
// in principle, this shouldn't happen, since @GenericGenerator
// constrains the type to subtypes of InMemoryGenerator
throw new MappingException( clazz.getName() + " does not implement 'InMemoryGenerator'" );
}
return clazz;
}
catch ( ClassLoadingException e ) {
throw new MappingException( String.format( "Could not interpret id generator strategy [%s]", strategy ) );
}
}
else {
return generatorClass;
}
}
}

View File

@ -12,7 +12,8 @@ import java.util.UUID;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.id.factory.spi.CustomIdGeneratorCreationContext;
import org.hibernate.id.factory.spi.StandardGenerator;
import org.hibernate.tuple.GenerationTiming;
import org.hibernate.tuple.InMemoryGenerator;
import org.hibernate.type.descriptor.java.UUIDJavaType;
import org.hibernate.type.descriptor.java.UUIDJavaType.ValueTransformer;
@ -24,7 +25,7 @@ import static org.hibernate.internal.util.ReflectHelper.getPropertyType;
*
* @see org.hibernate.annotations.UuidGenerator
*/
public class UuidGenerator implements StandardGenerator {
public class UuidGenerator implements InMemoryGenerator {
interface ValueGenerator {
UUID generateUuid(SharedSessionContractImplementor session);
}
@ -59,7 +60,13 @@ public class UuidGenerator implements StandardGenerator {
}
}
public Object generate(SharedSessionContractImplementor session, Object object) throws HibernateException {
@Override
public GenerationTiming getGenerationTiming() {
return GenerationTiming.INSERT;
}
@Override
public Object generate(SharedSessionContractImplementor session, Object owner, Object currentValue) {
return valueTransformer.transform( generator.generateUuid( session ) );
}
}

View File

@ -59,7 +59,7 @@ public interface KeyValue extends Value {
}
/**
* We need to add {@code Column.isIdentity()}.
* @deprecated We need to add {@code Column.isIdentity()}
*/
@Deprecated(since="6.2")
boolean isIdentityColumn(IdentifierGeneratorFactory identifierGeneratorFactory, Dialect dialect);

View File

@ -26,8 +26,10 @@ import java.io.Serializable;
* statement. In this case, the generated value is retrieved from the database using a SQL
* {@code select}.
* </ul>
* A generator may receive parameters from {@linkplain org.hibernate.annotations.ValueGenerationType
* an annotation}. The generator may either:
* Generically, a generator may be integrated with the program using the meta-annotation
* {@link org.hibernate.annotations.ValueGenerationType}, which associates the generator with
* a Java annotation type, called the <em>generator annotation</em>. A generator may receive
* parameters from its generator annotation. The generator may either:
* <ul>
* <li>implement {@link AnnotationBasedGenerator}, and receive the annotation as an argument to
* {@link AnnotationBasedGenerator#initialize},
@ -35,14 +37,10 @@ import java.io.Serializable;
* <li>declare a constructor which accepts just the annotation instance, or
* <li>declare a only default constructor, in which case it will not receive parameters.
* </ul>
* On the other hand, there is some special machinery for configuring the much older interface
* {@link org.hibernate.id.IdentifierGenerator}. But this machinery is only available for
* identifier generation.
*
* @see org.hibernate.annotations.ValueGenerationType
* @see org.hibernate.annotations.IdGeneratorType
* @see org.hibernate.annotations.Generated
* @see org.hibernate.annotations.GeneratorType
*
* @author Steve Ebersole
* @author Gavin King

View File

@ -10,15 +10,24 @@ import org.hibernate.engine.spi.SharedSessionContractImplementor;
/**
* A generator that is called to produce a value just before a row is written to the database.
* The {@link #generate} method may execute arbitrary Java code, it may even, in principle,
* access the database via JDBC. But however it is produced, the generated value is sent to the
* The {@link #generate} method may execute arbitrary Java code. It may even, in principle,
* access the database via JDBC. But however it's produced, the generated value is sent to the
* database via a parameter of a JDBC prepared statement, just like any other field or property
* value.
* <p>
* Any {@link InMemoryGenerator} may be used to produce {@linkplain jakarta.persistence.Id
* Any {@link InMemoryGenerator} with {@linkplain #getGenerationTiming() generation timing}
* {@link GenerationTiming#INSERT} may be used to produce {@linkplain jakarta.persistence.Id
* identifiers}. The built-in identifier generators all implement the older extension point
* {@link org.hibernate.id.IdentifierGenerator}, which is a subtype of this interface, but that
* is no longer a requirement for custom id generators.
* <p>
* A custom id generator may be integrated with the program using either:
* <ul>
* <li>the meta-annotation {@link org.hibernate.annotations.IdGeneratorType} or
* <li>the annotation {@link org.hibernate.annotations.GenericGenerator}.
* </ul>
* On the other hand, generators for regular fields and properties may be integrated using
* {@link org.hibernate.annotations.ValueGenerationType}, as for any {@link Generator}.
*
* @author Steve Ebersole
*