clean up SequenceStyleGenerator + StandardOptimizerDescriptor

This commit is contained in:
Gavin 2023-04-11 08:45:25 +02:00 committed by Gavin King
parent b682a1036c
commit 91eb9e1f20
8 changed files with 257 additions and 187 deletions

View File

@ -0,0 +1,34 @@
/*
* 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.enhanced;
import org.hibernate.internal.util.ReflectHelper;
/**
* @author Gavin King
*/
public class CustomOptimizerDescriptor implements OptimizerDescriptor {
private final String className;
CustomOptimizerDescriptor(String className) {
this.className = className;
}
@Override
public boolean isPooled() {
return false;
}
@Override
public String getExternalName() {
return className;
}
@Override
public Class<? extends Optimizer> getOptimizerClass() throws ClassNotFoundException {
return ReflectHelper.classForName( className );
}
}

View File

@ -0,0 +1,17 @@
/*
* 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.enhanced;
/**
* @author Gavin King
*/
public interface OptimizerDescriptor {
boolean isPooled();
String getExternalName();
Class<? extends Optimizer> getOptimizerClass()
throws ClassNotFoundException;
}

View File

@ -11,12 +11,11 @@ import java.util.Properties;
import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.AvailableSettings;
import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.internal.util.config.ConfigurationHelper;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
import static org.hibernate.internal.util.StringHelper.isNotEmpty;
/** /**
* Factory for {@link Optimizer} instances. * Factory for {@link Optimizer} instances.
* *
@ -34,59 +33,54 @@ public class OptimizerFactory {
* @param optimizerName The name of the optimizer * @param optimizerName The name of the optimizer
* *
* @return {@code true} indicates the optimizer is a pooled strategy. * @return {@code true} indicates the optimizer is a pooled strategy.
*
* @deprecated No longer used
*/ */
@Deprecated(since = "6.3")
public static boolean isPooledOptimizer(String optimizerName) { public static boolean isPooledOptimizer(String optimizerName) {
final StandardOptimizerDescriptor standardDescriptor = StandardOptimizerDescriptor.fromExternalName( optimizerName ); return StandardOptimizerDescriptor.fromExternalName( optimizerName ).isPooled();
return standardDescriptor != null && standardDescriptor.isPooled();
} }
private static final Class[] CTOR_SIG = new Class[] { Class.class, int.class }; private static final Class<?>[] CTOR_SIG = new Class[] { Class.class, int.class };
private static Optimizer buildOptimizer(String type, Class returnClass, int incrementSize) { private static Optimizer buildOptimizer(OptimizerDescriptor descriptor, Class<?> returnClass, int incrementSize) {
final Class<? extends Optimizer> optimizerClass; final Class<? extends Optimizer> optimizerClass;
try {
final StandardOptimizerDescriptor standardDescriptor = StandardOptimizerDescriptor.fromExternalName( type ); optimizerClass = descriptor.getOptimizerClass();
if ( standardDescriptor != null ) {
optimizerClass = standardDescriptor.getOptimizerClass();
} }
else { catch ( Throwable ignore ) {
try { LOG.unableToLocateCustomOptimizerClass( descriptor.getExternalName() );
optimizerClass = ReflectHelper.classForName( type ); return buildFallbackOptimizer( returnClass, incrementSize );
}
catch( Throwable ignore ) {
LOG.unableToLocateCustomOptimizerClass( type );
return buildFallbackOptimizer( returnClass, incrementSize );
}
} }
try { try {
final Constructor ctor = optimizerClass.getConstructor( CTOR_SIG ); final Constructor<? extends Optimizer> ctor = optimizerClass.getConstructor( CTOR_SIG );
return (Optimizer) ctor.newInstance( returnClass, incrementSize ); return ctor.newInstance( returnClass, incrementSize );
} }
catch( Throwable ignore ) { catch ( Throwable ignore ) {
LOG.unableToInstantiateOptimizer( type ); LOG.unableToInstantiateOptimizer( descriptor.getExternalName() );
} }
return buildFallbackOptimizer( returnClass, incrementSize ); return buildFallbackOptimizer( returnClass, incrementSize );
} }
private static Optimizer buildFallbackOptimizer(Class returnClass, int incrementSize) { private static Optimizer buildFallbackOptimizer(Class<?> returnClass, int incrementSize) {
return new NoopOptimizer( returnClass, incrementSize ); return new NoopOptimizer( returnClass, incrementSize );
} }
/** /**
* Builds an optimizer * Builds an optimizer
* *
* @param type The optimizer type, either a short-hand name or the {@link Optimizer} class name. * @param type The optimizer type, either a shorthand name or the {@link Optimizer} class name.
* @param returnClass The generated value java type * @param returnClass The generated value java type
* @param incrementSize The increment size. * @param incrementSize The increment size.
* @param explicitInitialValue The user supplied initial-value (-1 indicates the user did not specify). * @param explicitInitialValue The user supplied initial-value (-1 indicates the user did not specify).
* *
* @return The built optimizer * @return The built optimizer
*/ */
public static Optimizer buildOptimizer(String type, Class returnClass, int incrementSize, long explicitInitialValue) { public static Optimizer buildOptimizer(OptimizerDescriptor type, Class<?> returnClass, int incrementSize, long explicitInitialValue) {
final Optimizer optimizer = buildOptimizer( type, returnClass, incrementSize ); final Optimizer optimizer = buildOptimizer( type, returnClass, incrementSize );
if ( InitialValueAwareOptimizer.class.isInstance( optimizer ) ) { if ( optimizer instanceof InitialValueAwareOptimizer ) {
( (InitialValueAwareOptimizer) optimizer ).injectInitialValue( explicitInitialValue ); ( (InitialValueAwareOptimizer) optimizer ).injectInitialValue( explicitInitialValue );
} }
return optimizer; return optimizer;
@ -99,15 +93,18 @@ public class OptimizerFactory {
if ( incrementSize <= 1 ) { if ( incrementSize <= 1 ) {
return StandardOptimizerDescriptor.NONE.getExternalName(); return StandardOptimizerDescriptor.NONE.getExternalName();
} }
else {
// see if the user defined a preferred pooled optimizer... // see if the user defined a preferred pooled optimizer...
final String preferredPooledOptimizerStrategy = configSettings.getProperty( AvailableSettings.PREFERRED_POOLED_OPTIMIZER ); final String preferredPooledOptimizerStrategy =
if ( StringHelper.isNotEmpty( preferredPooledOptimizerStrategy ) ) { configSettings.getProperty( AvailableSettings.PREFERRED_POOLED_OPTIMIZER );
return preferredPooledOptimizerStrategy; if ( isNotEmpty( preferredPooledOptimizerStrategy ) ) {
return preferredPooledOptimizerStrategy;
}
else {
// otherwise fallback to the fallback strategy
return StandardOptimizerDescriptor.POOLED.getExternalName();
}
} }
// otherwise fallback to the fallback strategy
return StandardOptimizerDescriptor.POOLED.getExternalName();
} }
private OptimizerFactory() { private OptimizerFactory() {

View File

@ -15,6 +15,7 @@ import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.boot.model.relational.Database; import org.hibernate.boot.model.relational.Database;
import org.hibernate.boot.model.relational.QualifiedName; import org.hibernate.boot.model.relational.QualifiedName;
import org.hibernate.boot.model.relational.QualifiedNameParser; import org.hibernate.boot.model.relational.QualifiedNameParser;
import org.hibernate.boot.model.relational.QualifiedSequenceName;
import org.hibernate.boot.model.relational.SqlStringGenerationContext; import org.hibernate.boot.model.relational.SqlStringGenerationContext;
import org.hibernate.boot.registry.selector.spi.StrategySelector; import org.hibernate.boot.registry.selector.spi.StrategySelector;
import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.AvailableSettings;
@ -28,7 +29,6 @@ import org.hibernate.id.PersistentIdentifierGenerator;
import org.hibernate.id.SequenceMismatchStrategy; import org.hibernate.id.SequenceMismatchStrategy;
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.internal.util.config.ConfigurationHelper;
import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistry;
import org.hibernate.tool.schema.extract.spi.SequenceInformation; import org.hibernate.tool.schema.extract.spi.SequenceInformation;
import org.hibernate.type.Type; import org.hibernate.type.Type;
@ -36,8 +36,12 @@ import org.hibernate.type.Type;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
import static org.hibernate.cfg.AvailableSettings.ID_DB_STRUCTURE_NAMING_STRATEGY; import static org.hibernate.cfg.AvailableSettings.ID_DB_STRUCTURE_NAMING_STRATEGY;
import static org.hibernate.id.enhanced.OptimizerFactory.determineImplicitOptimizerName;
import static org.hibernate.internal.log.IncubationLogger.INCUBATION_LOGGER; import static org.hibernate.internal.log.IncubationLogger.INCUBATION_LOGGER;
import static org.hibernate.internal.util.NullnessHelper.coalesceSuppliedValues; import static org.hibernate.internal.util.NullnessHelper.coalesceSuppliedValues;
import static org.hibernate.internal.util.config.ConfigurationHelper.getBoolean;
import static org.hibernate.internal.util.config.ConfigurationHelper.getInt;
import static org.hibernate.internal.util.config.ConfigurationHelper.getString;
/** /**
* Generates identifier values based on a sequence-style database structure. * Generates identifier values based on a sequence-style database structure.
@ -188,64 +192,32 @@ public class SequenceStyleGenerator
@Override @Override
public void configure(Type type, Properties parameters, ServiceRegistry serviceRegistry) throws MappingException { public void configure(Type type, Properties parameters, ServiceRegistry serviceRegistry) throws MappingException {
final JdbcEnvironment jdbcEnvironment = serviceRegistry.getService( JdbcEnvironment.class ); final JdbcEnvironment jdbcEnvironment = serviceRegistry.getService( JdbcEnvironment.class );
final ConfigurationService configurationService = serviceRegistry.getService( ConfigurationService.class );
final Dialect dialect = jdbcEnvironment.getDialect(); final Dialect dialect = jdbcEnvironment.getDialect();
this.identifierType = type; this.identifierType = type;
boolean forceTableUse = ConfigurationHelper.getBoolean( FORCE_TBL_PARAM, parameters, false );
final QualifiedName sequenceName = determineSequenceName( parameters, dialect, jdbcEnvironment, serviceRegistry ); final QualifiedName sequenceName = determineSequenceName( parameters, dialect, jdbcEnvironment, serviceRegistry );
final int initialValue = determineInitialValue( parameters ); final int initialValue = determineInitialValue( parameters );
int incrementSize = determineIncrementSize( parameters ); int incrementSize = determineIncrementSize( parameters );
final OptimizerDescriptor optimizationStrategy = determineOptimizationStrategy( parameters, incrementSize );
final String optimizationStrategy = determineOptimizationStrategy(parameters, incrementSize ); boolean forceTableUse = getBoolean( FORCE_TBL_PARAM, parameters, false );
final boolean physicalSequence = isPhysicalSequence( jdbcEnvironment, forceTableUse );
final boolean isPooledOptimizer = OptimizerFactory.isPooledOptimizer( optimizationStrategy ); incrementSize = adjustIncrementSize(
jdbcEnvironment,
sequenceName,
SequenceMismatchStrategy sequenceMismatchStrategy = configurationService.getSetting( incrementSize,
AvailableSettings.SEQUENCE_INCREMENT_SIZE_MISMATCH_STRATEGY, physicalSequence,
SequenceMismatchStrategy::interpret, optimizationStrategy,
SequenceMismatchStrategy.EXCEPTION serviceRegistry
); );
if ( sequenceMismatchStrategy != SequenceMismatchStrategy.NONE if ( physicalSequence
&& isPooledOptimizer && optimizationStrategy.isPooled()
&& isPhysicalSequence( jdbcEnvironment, forceTableUse ) ) { && !dialect.getSequenceSupport().supportsPooledSequences() ) {
String databaseSequenceName = sequenceName.getObjectName().getText(); forceTableUse = true;
Number databaseIncrementValue = getSequenceIncrementValue( jdbcEnvironment, databaseSequenceName ); LOG.forcingTableUse();
if ( databaseIncrementValue != null && databaseIncrementValue.intValue() != incrementSize ) {
int dbIncrementValue = databaseIncrementValue.intValue();
switch ( sequenceMismatchStrategy ) {
case EXCEPTION:
throw new MappingException(
String.format(
"The increment size of the [%s] sequence is set to [%d] in the entity mapping " +
"while the associated database sequence increment size is [%d].",
databaseSequenceName, incrementSize, dbIncrementValue
)
);
case FIX:
incrementSize = dbIncrementValue;
case LOG:
LOG.sequenceIncrementSizeMismatch( databaseSequenceName, incrementSize, dbIncrementValue );
break;
}
}
}
incrementSize = determineAdjustedIncrementSize( optimizationStrategy, incrementSize );
if ( dialect.getSequenceSupport().supportsSequences() && !forceTableUse ) {
if ( !dialect.getSequenceSupport().supportsPooledSequences()
&& OptimizerFactory.isPooledOptimizer( optimizationStrategy ) ) {
forceTableUse = true;
LOG.forcingTableUse();
}
} }
this.databaseStructure = buildDatabaseStructure( this.databaseStructure = buildDatabaseStructure(
@ -261,11 +233,53 @@ public class SequenceStyleGenerator
optimizationStrategy, optimizationStrategy,
identifierType.getReturnedClass(), identifierType.getReturnedClass(),
incrementSize, incrementSize,
ConfigurationHelper.getInt( INITIAL_PARAM, parameters, -1 ) getInt( INITIAL_PARAM, parameters, -1 )
); );
this.databaseStructure.configure( optimizer ); this.databaseStructure.configure( optimizer );
} }
private int adjustIncrementSize(
JdbcEnvironment jdbcEnvironment,
QualifiedName sequenceName,
int incrementSize,
boolean physicalSequence,
OptimizerDescriptor optimizationStrategy,
ServiceRegistry serviceRegistry) {
final ConfigurationService configurationService = serviceRegistry.getService( ConfigurationService.class );
final SequenceMismatchStrategy sequenceMismatchStrategy = configurationService.getSetting(
AvailableSettings.SEQUENCE_INCREMENT_SIZE_MISMATCH_STRATEGY,
SequenceMismatchStrategy::interpret,
SequenceMismatchStrategy.EXCEPTION
);
if ( sequenceMismatchStrategy != SequenceMismatchStrategy.NONE
&& optimizationStrategy.isPooled()
&& physicalSequence ) {
final String databaseSequenceName = sequenceName.getObjectName().getText();
final Number databaseIncrementValue = getSequenceIncrementValue( jdbcEnvironment, databaseSequenceName );
if ( databaseIncrementValue != null && databaseIncrementValue.intValue() != incrementSize) {
final int dbIncrementValue = databaseIncrementValue.intValue();
switch ( sequenceMismatchStrategy ) {
case EXCEPTION:
throw new MappingException(
String.format(
"The increment size of the [%s] sequence is set to [%d] in the entity mapping "
+ "while the associated database sequence increment size is [%d].",
databaseSequenceName, incrementSize, dbIncrementValue
)
);
case FIX:
incrementSize = dbIncrementValue;
case LOG:
//TODO: the log message is correct for the case of FIX, but wrong for LOG
LOG.sequenceIncrementSizeMismatch( databaseSequenceName, incrementSize, dbIncrementValue );
break;
}
}
}
return determineAdjustedIncrementSize( optimizationStrategy, incrementSize );
}
@Override @Override
public void registerExportables(Database database) { public void registerExportables(Database database) {
databaseStructure.registerExportables( database ); databaseStructure.registerExportables( database );
@ -294,16 +308,16 @@ public class SequenceStyleGenerator
JdbcEnvironment jdbcEnv, JdbcEnvironment jdbcEnv,
ServiceRegistry serviceRegistry) { ServiceRegistry serviceRegistry) {
final Identifier catalog = jdbcEnv.getIdentifierHelper().toIdentifier( final Identifier catalog = jdbcEnv.getIdentifierHelper().toIdentifier(
ConfigurationHelper.getString( CATALOG, params ) getString( CATALOG, params )
); );
final Identifier schema = jdbcEnv.getIdentifierHelper().toIdentifier( final Identifier schema = jdbcEnv.getIdentifierHelper().toIdentifier(
ConfigurationHelper.getString( SCHEMA, params ) getString( SCHEMA, params )
); );
final String sequenceName = ConfigurationHelper.getString( final String sequenceName = getString(
SEQUENCE_PARAM, SEQUENCE_PARAM,
params, params,
() -> ConfigurationHelper.getString( ALT_SEQUENCE_PARAM, params ) () -> getString( ALT_SEQUENCE_PARAM, params )
); );
if ( StringHelper.isNotEmpty( sequenceName ) ) { if ( StringHelper.isNotEmpty( sequenceName ) ) {
@ -333,7 +347,7 @@ public class SequenceStyleGenerator
final String namingStrategySetting = coalesceSuppliedValues( final String namingStrategySetting = coalesceSuppliedValues(
() -> { () -> {
final String localSetting = ConfigurationHelper.getString( ID_DB_STRUCTURE_NAMING_STRATEGY, params ); final String localSetting = getString( ID_DB_STRUCTURE_NAMING_STRATEGY, params );
if ( localSetting != null ) { if ( localSetting != null ) {
INCUBATION_LOGGER.incubatingSetting( ID_DB_STRUCTURE_NAMING_STRATEGY ); INCUBATION_LOGGER.incubatingSetting( ID_DB_STRUCTURE_NAMING_STRATEGY );
} }
@ -341,7 +355,7 @@ public class SequenceStyleGenerator
}, },
() -> { () -> {
final ConfigurationService configurationService = serviceRegistry.getService( ConfigurationService.class ); final ConfigurationService configurationService = serviceRegistry.getService( ConfigurationService.class );
final String globalSetting = ConfigurationHelper.getString( ID_DB_STRUCTURE_NAMING_STRATEGY, configurationService.getSettings() ); final String globalSetting = getString( ID_DB_STRUCTURE_NAMING_STRATEGY, configurationService.getSettings() );
if ( globalSetting != null ) { if ( globalSetting != null ) {
INCUBATION_LOGGER.incubatingSetting( ID_DB_STRUCTURE_NAMING_STRATEGY ); INCUBATION_LOGGER.incubatingSetting( ID_DB_STRUCTURE_NAMING_STRATEGY );
} }
@ -370,7 +384,7 @@ public class SequenceStyleGenerator
* @return The value column name * @return The value column name
*/ */
protected Identifier determineValueColumnName(Properties params, JdbcEnvironment jdbcEnvironment) { protected Identifier determineValueColumnName(Properties params, JdbcEnvironment jdbcEnvironment) {
final String name = ConfigurationHelper.getString( VALUE_COLUMN_PARAM, params, DEF_VALUE_COLUMN ); final String name = getString( VALUE_COLUMN_PARAM, params, DEF_VALUE_COLUMN );
return jdbcEnvironment.getIdentifierHelper().toIdentifier( name ); return jdbcEnvironment.getIdentifierHelper().toIdentifier( name );
} }
@ -385,7 +399,7 @@ public class SequenceStyleGenerator
* @return The initial value * @return The initial value
*/ */
protected int determineInitialValue(Properties params) { protected int determineInitialValue(Properties params) {
return ConfigurationHelper.getInt( INITIAL_PARAM, params, DEFAULT_INITIAL_VALUE ); return getInt( INITIAL_PARAM, params, DEFAULT_INITIAL_VALUE );
} }
/** /**
@ -398,7 +412,7 @@ public class SequenceStyleGenerator
* @return The increment size * @return The increment size
*/ */
protected int determineIncrementSize(Properties params) { protected int determineIncrementSize(Properties params) {
return ConfigurationHelper.getInt( INCREMENT_PARAM, params, DEFAULT_INCREMENT_SIZE ); return getInt( INCREMENT_PARAM, params, DEFAULT_INCREMENT_SIZE );
} }
/** /**
@ -406,15 +420,13 @@ public class SequenceStyleGenerator
* <p> * <p>
* Called during {@linkplain #configure configuration}. * Called during {@linkplain #configure configuration}.
* *
* @param params The params supplied in the generator config (plus some standard useful extras). * @param params The params supplied in the generator config (plus some standard useful extras).
* @param incrementSize The {@link #determineIncrementSize determined increment size} * @param incrementSize The {@link #determineIncrementSize determined increment size}
* @return The optimizer strategy (name) * @return The optimizer strategy (name)
*/ */
protected String determineOptimizationStrategy(Properties params, int incrementSize) { protected OptimizerDescriptor determineOptimizationStrategy(Properties params, int incrementSize) {
return ConfigurationHelper.getString( return StandardOptimizerDescriptor.fromExternalName(
OPT_PARAM, getString( OPT_PARAM, params, determineImplicitOptimizerName( incrementSize, params ) )
params,
OptimizerFactory.determineImplicitOptimizerName( incrementSize, params )
); );
} }
@ -426,36 +438,35 @@ public class SequenceStyleGenerator
* @param incrementSize The {@link #determineIncrementSize determined increment size} * @param incrementSize The {@link #determineIncrementSize determined increment size}
* @return The adjusted increment size. * @return The adjusted increment size.
*/ */
protected int determineAdjustedIncrementSize(String optimizationStrategy, int incrementSize) { protected int determineAdjustedIncrementSize(OptimizerDescriptor optimizationStrategy, int incrementSize) {
final int resolvedIncrementSize; if ( optimizationStrategy == StandardOptimizerDescriptor.NONE ) {
if ( Math.abs( incrementSize ) > 1 &&
StandardOptimizerDescriptor.NONE.getExternalName().equals( optimizationStrategy ) ) {
if ( incrementSize < -1 ) { if ( incrementSize < -1 ) {
resolvedIncrementSize = -1;
LOG.honoringOptimizerSetting( LOG.honoringOptimizerSetting(
StandardOptimizerDescriptor.NONE.getExternalName(), StandardOptimizerDescriptor.NONE.getExternalName(),
INCREMENT_PARAM, INCREMENT_PARAM,
incrementSize, incrementSize,
"negative", "negative",
resolvedIncrementSize -1
); );
return -1;
} }
else { else if ( incrementSize > 1 ) {
// incrementSize > 1
resolvedIncrementSize = 1;
LOG.honoringOptimizerSetting( LOG.honoringOptimizerSetting(
StandardOptimizerDescriptor.NONE.getExternalName(), StandardOptimizerDescriptor.NONE.getExternalName(),
INCREMENT_PARAM, INCREMENT_PARAM,
incrementSize, incrementSize,
"positive", "positive",
resolvedIncrementSize 1
); );
return 1;
}
else {
return incrementSize;
} }
} }
else { else {
resolvedIncrementSize = incrementSize; return incrementSize;
} }
return resolvedIncrementSize;
} }
/** /**
@ -571,11 +582,12 @@ public class SequenceStyleGenerator
.stream() .stream()
.filter( .filter(
sequenceInformation -> { sequenceInformation -> {
Identifier catalog = sequenceInformation.getSequenceName().getCatalogName(); QualifiedSequenceName name = sequenceInformation.getSequenceName();
Identifier schema = sequenceInformation.getSequenceName().getSchemaName(); Identifier catalog = name.getCatalogName();
return sequenceName.equalsIgnoreCase( sequenceInformation.getSequenceName().getSequenceName().getText() ) && Identifier schema = name.getSchemaName();
( catalog == null || catalog.equals( jdbcEnvironment.getCurrentCatalog() ) ) && return sequenceName.equalsIgnoreCase( name.getSequenceName().getText() )
( schema == null || schema.equals( jdbcEnvironment.getCurrentSchema() ) ); && ( catalog == null || catalog.equals( jdbcEnvironment.getCurrentCatalog() ) )
&& ( schema == null || schema.equals( jdbcEnvironment.getCurrentSchema() ) );
} }
) )
.map( SequenceInformation::getIncrementValue ) .map( SequenceInformation::getIncrementValue )

View File

@ -6,72 +6,97 @@
*/ */
package org.hibernate.id.enhanced; package org.hibernate.id.enhanced;
import org.hibernate.internal.util.StringHelper; import org.hibernate.AssertionFailure;
import org.jboss.logging.Logger; import static org.hibernate.internal.util.StringHelper.isEmpty;
/** /**
* Enumeration of the standard Hibernate id generation optimizers. * Enumeration of the standard Hibernate id generation optimizers.
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public enum StandardOptimizerDescriptor { public enum StandardOptimizerDescriptor implements OptimizerDescriptor {
/** /**
* Describes the optimizer for no optimization. * Describes the optimizer for no optimization.
*/ */
NONE( "none", NoopOptimizer.class ), NONE,
/** /**
* Describes the optimizer for using a custom "hilo" algorithm optimization. * Describes the optimizer for using a custom "hilo" algorithm optimization.
*/ */
HILO( "hilo", HiLoOptimizer.class ), HILO,
/** /**
* Describes the optimizer for using a custom "hilo" algorithm optimization, following the * Describes the optimizer for using a custom "hilo" algorithm optimization, following the
* legacy Hibernate hilo algorithm. * legacy Hibernate hilo algorithm.
*/ */
LEGACY_HILO( "legacy-hilo", LegacyHiLoAlgorithmOptimizer.class ), LEGACY_HILO,
/** /**
* Describes the optimizer for use with tables/sequences that store the chunk information. * Describes the optimizer for use with tables/sequences that store the chunk information.
* Here, specifically the hi value is stored in the database. * Here, specifically the hi value is stored in the database.
*/ */
POOLED( "pooled", PooledOptimizer.class, true ), POOLED,
/** /**
* Describes the optimizer for use with tables/sequences that store the chunk information. * Describes the optimizer for use with tables/sequences that store the chunk information.
* Here, specifically the lo value is stored in the database. * Here, specifically the lo value is stored in the database.
*/ */
POOLED_LO( "pooled-lo", PooledLoOptimizer.class, true ), POOLED_LO,
/** /**
* Describes the optimizer for use with tables/sequences that store the chunk information. * Describes the optimizer for use with tables/sequences that store the chunk information.
* Here, specifically the lo value is stored in the database and ThreadLocal used to cache * Here, specifically the lo value is stored in the database and ThreadLocal used to cache
* the generation state. * the generation state.
*/ */
POOLED_LOTL( "pooled-lotl", PooledLoThreadLocalOptimizer.class, true ); POOLED_LOTL;
private static final Logger log = Logger.getLogger( StandardOptimizerDescriptor.class );
private final String externalName;
private final Class<? extends Optimizer> optimizerClass;
private final boolean isPooled;
StandardOptimizerDescriptor(String externalName, Class<? extends Optimizer> optimizerClass) {
this( externalName, optimizerClass, false );
}
StandardOptimizerDescriptor(String externalName, Class<? extends Optimizer> optimizerClass, boolean pooled) {
this.externalName = externalName;
this.optimizerClass = optimizerClass;
this.isPooled = pooled;
}
@Override
public String getExternalName() { public String getExternalName() {
return externalName; switch ( this ) {
case NONE:
return "none";
case HILO:
return "hilo";
case LEGACY_HILO:
return "legacy-hilo";
case POOLED:
return "pooled";
case POOLED_LO:
return "pooled-lo";
case POOLED_LOTL:
return "pooled-lotl";
}
throw new AssertionFailure( "unknown StandardOptimizerDescriptor" );
} }
@Override
public Class<? extends Optimizer> getOptimizerClass() { public Class<? extends Optimizer> getOptimizerClass() {
return optimizerClass; switch ( this ) {
case NONE:
return NoopOptimizer.class;
case HILO:
return HiLoOptimizer.class;
case LEGACY_HILO:
return LegacyHiLoAlgorithmOptimizer.class;
case POOLED:
return PooledOptimizer.class;
case POOLED_LO:
return PooledLoOptimizer.class;
case POOLED_LOTL:
return PooledLoThreadLocalOptimizer.class;
}
throw new AssertionFailure( "unknown StandardOptimizerDescriptor" );
} }
@Override
public boolean isPooled() { public boolean isPooled() {
return isPooled; switch ( this ) {
case NONE:
case HILO:
case LEGACY_HILO:
return false;
case POOLED:
case POOLED_LO:
case POOLED_LOTL:
return true;
}
throw new AssertionFailure( "unknown StandardOptimizerDescriptor" );
} }
/** /**
@ -83,32 +108,17 @@ public enum StandardOptimizerDescriptor {
* {@link #NONE} is returned; if an unrecognized external name is supplied, * {@link #NONE} is returned; if an unrecognized external name is supplied,
* {@code null} is returned * {@code null} is returned
*/ */
public static StandardOptimizerDescriptor fromExternalName(String externalName) { public static OptimizerDescriptor fromExternalName(String externalName) {
if ( StringHelper.isEmpty( externalName ) ) { if ( isEmpty( externalName ) ) {
log.debug( "No optimizer specified, using NONE as default" );
return NONE; return NONE;
} }
else if ( NONE.externalName.equals( externalName ) ) {
return NONE;
}
else if ( HILO.externalName.equals( externalName ) ) {
return HILO;
}
else if ( LEGACY_HILO.externalName.equals( externalName ) ) {
return LEGACY_HILO;
}
else if ( POOLED.externalName.equals( externalName ) ) {
return POOLED;
}
else if ( POOLED_LO.externalName.equals( externalName ) ) {
return POOLED_LO;
}
else if ( POOLED_LOTL.externalName.equals( externalName ) ) {
return POOLED_LOTL;
}
else { else {
log.debugf( "Unknown optimizer key [%s]; returning null assuming Optimizer impl class name", externalName ); for ( StandardOptimizerDescriptor value: values() ) {
return null; if ( value.getExternalName().equals( externalName ) ) {
return value;
}
}
return new CustomOptimizerDescriptor( externalName );
} }
} }
} }

View File

@ -11,7 +11,6 @@ import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Types; import java.sql.Types;
import java.util.Collections;
import java.util.Map; import java.util.Map;
import java.util.Properties; import java.util.Properties;
@ -53,7 +52,9 @@ import org.hibernate.type.Type;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
import static java.util.Collections.singletonMap;
import static org.hibernate.cfg.AvailableSettings.ID_DB_STRUCTURE_NAMING_STRATEGY; import static org.hibernate.cfg.AvailableSettings.ID_DB_STRUCTURE_NAMING_STRATEGY;
import static org.hibernate.id.enhanced.OptimizerFactory.determineImplicitOptimizerName;
import static org.hibernate.internal.log.IncubationLogger.INCUBATION_LOGGER; import static org.hibernate.internal.log.IncubationLogger.INCUBATION_LOGGER;
import static org.hibernate.internal.util.NullnessHelper.coalesceSuppliedValues; import static org.hibernate.internal.util.NullnessHelper.coalesceSuppliedValues;
import static org.hibernate.internal.util.config.ConfigurationHelper.getBoolean; import static org.hibernate.internal.util.config.ConfigurationHelper.getBoolean;
@ -336,27 +337,21 @@ public class TableGenerator implements PersistentIdentifierGenerator {
final JdbcEnvironment jdbcEnvironment = serviceRegistry.getService( JdbcEnvironment.class ); final JdbcEnvironment jdbcEnvironment = serviceRegistry.getService( JdbcEnvironment.class );
qualifiedTableName = determineGeneratorTableName(parameters, jdbcEnvironment, serviceRegistry ); qualifiedTableName = determineGeneratorTableName( parameters, jdbcEnvironment, serviceRegistry );
segmentColumnName = determineSegmentColumnName(parameters, jdbcEnvironment ); segmentColumnName = determineSegmentColumnName( parameters, jdbcEnvironment );
valueColumnName = determineValueColumnName(parameters, jdbcEnvironment ); valueColumnName = determineValueColumnName( parameters, jdbcEnvironment );
segmentValue = determineSegmentValue(parameters); segmentValue = determineSegmentValue( parameters );
segmentValueLength = determineSegmentColumnSize(parameters); segmentValueLength = determineSegmentColumnSize( parameters );
initialValue = determineInitialValue(parameters); initialValue = determineInitialValue( parameters );
incrementSize = determineIncrementSize(parameters); incrementSize = determineIncrementSize( parameters );
final String optimizationStrategy = getString(
OPT_PARAM,
parameters,
OptimizerFactory.determineImplicitOptimizerName( incrementSize, parameters)
);
int optimizerInitialValue = getInt( INITIAL_PARAM, parameters, -1 );
optimizer = OptimizerFactory.buildOptimizer( optimizer = OptimizerFactory.buildOptimizer(
optimizationStrategy, determineOptimizationStrategy( parameters, incrementSize ),
identifierType.getReturnedClass(), identifierType.getReturnedClass(),
incrementSize, incrementSize,
optimizerInitialValue getInt( INITIAL_PARAM, parameters, -1 )
); );
contributor = parameters.getProperty( CONTRIBUTOR_NAME ); contributor = parameters.getProperty( CONTRIBUTOR_NAME );
@ -365,6 +360,12 @@ public class TableGenerator implements PersistentIdentifierGenerator {
} }
} }
private static OptimizerDescriptor determineOptimizationStrategy(Properties parameters, int incrementSize) {
return StandardOptimizerDescriptor.fromExternalName(
getString( OPT_PARAM, parameters, determineImplicitOptimizerName( incrementSize, parameters ) )
);
}
/** /**
* Determine the table name to use for the generator values. * Determine the table name to use for the generator values.
* <p> * <p>
@ -515,7 +516,6 @@ public class TableGenerator implements PersistentIdentifierGenerator {
return getInt( INCREMENT_PARAM, params, DEFAULT_INCREMENT_SIZE ); return getInt( INCREMENT_PARAM, params, DEFAULT_INCREMENT_SIZE );
} }
@SuppressWarnings("unchecked")
protected String buildSelectQuery(String formattedPhysicalTableName, SqlStringGenerationContext context) { protected String buildSelectQuery(String formattedPhysicalTableName, SqlStringGenerationContext context) {
final String alias = "tbl"; final String alias = "tbl";
final String query = "select " + StringHelper.qualify( alias, valueColumnName ) final String query = "select " + StringHelper.qualify( alias, valueColumnName )
@ -523,7 +523,7 @@ public class TableGenerator implements PersistentIdentifierGenerator {
+ " where " + StringHelper.qualify( alias, segmentColumnName ) + "=?"; + " where " + StringHelper.qualify( alias, segmentColumnName ) + "=?";
final LockOptions lockOptions = new LockOptions( LockMode.PESSIMISTIC_WRITE ); final LockOptions lockOptions = new LockOptions( LockMode.PESSIMISTIC_WRITE );
lockOptions.setAliasSpecificLockMode( alias, LockMode.PESSIMISTIC_WRITE ); lockOptions.setAliasSpecificLockMode( alias, LockMode.PESSIMISTIC_WRITE );
final Map updateTargetColumnsMap = Collections.singletonMap( alias, new String[] { valueColumnName } ); final Map<String,String[]> updateTargetColumnsMap = singletonMap( alias, new String[] { valueColumnName } );
return context.getDialect().applyLocksToSql( query, lockOptions, updateTargetColumnsMap ); return context.getDialect().applyLocksToSql( query, lockOptions, updateTargetColumnsMap );
} }

View File

@ -176,7 +176,7 @@ public class OptimizerConcurrencyUnitTest extends BaseUnitTestCase {
} }
private Optimizer buildOptimizer(long initial, int increment) { private Optimizer buildOptimizer(long initial, int increment) {
return OptimizerFactory.buildOptimizer( optimizerDescriptor.getExternalName(), Long.class, increment, initial ); return OptimizerFactory.buildOptimizer( optimizerDescriptor, Long.class, increment, initial );
} }
private <R> R getDoneFutureValue(Future<R> future) { private <R> R getDoneFutureValue(Future<R> future) {

View File

@ -328,7 +328,7 @@ public class OptimizerUnitTest {
StandardOptimizerDescriptor descriptor, StandardOptimizerDescriptor descriptor,
long initial, long initial,
int increment) { int increment) {
return OptimizerFactory.buildOptimizer( descriptor.getExternalName(), Long.class, increment, initial ); return OptimizerFactory.buildOptimizer( descriptor, Long.class, increment, initial );
} }
private static class SourceMock implements AccessCallback { private static class SourceMock implements AccessCallback {