HHH-15143 - Add an "implicit naming strategy" for database structures (sequence and tables) for identifier generators

- clean up, javadoc, migration-guide
This commit is contained in:
Steve Ebersole 2022-03-29 20:58:35 -05:00
parent 56ba690366
commit e433f32fc6
13 changed files with 300 additions and 185 deletions

View File

@ -27,9 +27,9 @@ import org.hibernate.cache.spi.CacheKeysFactory;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform;
import org.hibernate.id.enhanced.ImplicitDatabaseObjectNamingStrategy;
import org.hibernate.id.enhanced.SingleNamingStrategy;
import org.hibernate.id.enhanced.LegacyNamingStrategy;
import org.hibernate.id.enhanced.LegacyPreferGeneratorNameNamingStrategy;
import org.hibernate.id.enhanced.StandardDatabaseObjectNamingStrategy;
import org.hibernate.id.enhanced.StandardNamingStrategy;
import org.hibernate.query.sqm.mutation.internal.cte.CteMutationStrategy;
import org.hibernate.query.sqm.mutation.internal.temptable.GlobalTemporaryTableMutationStrategy;
import org.hibernate.query.sqm.mutation.internal.temptable.LocalTemporaryTableMutationStrategy;
@ -223,8 +223,14 @@ public class StrategySelectorBuilder {
strategySelector.registerStrategyImplementor(
ImplicitDatabaseObjectNamingStrategy.class,
StandardDatabaseObjectNamingStrategy.STRATEGY_NAME,
StandardDatabaseObjectNamingStrategy.class
StandardNamingStrategy.STRATEGY_NAME,
StandardNamingStrategy.class
);
strategySelector.registerStrategyImplementor(
ImplicitDatabaseObjectNamingStrategy.class,
SingleNamingStrategy.STRATEGY_NAME,
SingleNamingStrategy.class
);
strategySelector.registerStrategyImplementor(
@ -232,12 +238,6 @@ public class StrategySelectorBuilder {
LegacyNamingStrategy.STRATEGY_NAME,
LegacyNamingStrategy.class
);
strategySelector.registerStrategyImplementor(
ImplicitDatabaseObjectNamingStrategy.class,
LegacyPreferGeneratorNameNamingStrategy.STRATEGY_NAME,
LegacyPreferGeneratorNameNamingStrategy.class
);
}
private void addCacheKeysFactories(StrategySelectorImpl strategySelector) {

View File

@ -15,6 +15,7 @@ import org.hibernate.CustomEntityDirtinessStrategy;
import org.hibernate.Incubating;
import org.hibernate.Interceptor;
import org.hibernate.SessionFactoryObserver;
import org.hibernate.boot.registry.selector.spi.StrategySelector;
import org.hibernate.id.enhanced.ImplicitDatabaseObjectNamingStrategy;
import org.hibernate.cache.spi.TimestampsCacheFactory;
import org.hibernate.context.spi.CurrentTenantIdentifierResolver;
@ -780,9 +781,17 @@ public interface AvailableSettings {
* An implicit naming-strategy for database structures (tables, sequences) related
* to identifier-generators
*
* @see ImplicitDatabaseObjectNamingStrategy
* Resolution uses the {@link org.hibernate.boot.registry.selector.spi.StrategySelector}
* service and accepts any of the forms discussed on
* {@link StrategySelector#resolveDefaultableStrategy}.
*
* @incubating `ImplicitDatabaseObjectNamingStrategy` is considered incubating
* The recognized short names being:<ul>
* <li>{@value org.hibernate.id.enhanced.SingleNamingStrategy#STRATEGY_NAME}</li>
* <li>{@value org.hibernate.id.enhanced.LegacyNamingStrategy#STRATEGY_NAME}</li>
* <li>{@value org.hibernate.id.enhanced.StandardNamingStrategy#STRATEGY_NAME}</li>
* </ul>
*
* @see ImplicitDatabaseObjectNamingStrategy
*/
@Incubating
String ID_DB_STRUCTURE_NAMING_STRATEGY = "hibernate.id.db_structure_naming_strategy";

View File

@ -8,46 +8,124 @@ package org.hibernate.id.enhanced;
import java.util.Map;
import jakarta.persistence.GeneratedValue;
import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.boot.model.relational.QualifiedName;
import org.hibernate.boot.model.relational.QualifiedNameParser;
import org.hibernate.boot.model.relational.QualifiedSequenceName;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.id.IdentifierGenerator;
import org.hibernate.id.PersistentIdentifierGenerator;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.internal.util.config.ConfigurationHelper;
import org.hibernate.service.ServiceRegistry;
import static org.hibernate.id.OptimizableGenerator.IMPLICIT_NAME_BASE;
import static org.hibernate.id.enhanced.SequenceStyleGenerator.CONFIG_SEQUENCE_PER_ENTITY_SUFFIX;
import static org.hibernate.id.enhanced.TableGenerator.DEF_TABLE;
/**
* @author Andrea Boriero
* Naming strategy which implements the behavior of older versions of
* Hibernate, for the most part.
*
* For sequences (including forced-table sequences):<ol>
* <li>
* If {@value SequenceStyleGenerator#CONFIG_SEQUENCE_PER_ENTITY_SUFFIX} is specified,
* a name composed of the "base" name with the specified suffix. The base name
* depends on the usage of the generator, but is generally the root entity-name if
* applied to an entity identifier or the table we are generating values for
* </li>
* <li>
* If annotations are used and {@link GeneratedValue#generator()} is specified,
* its value is used as the sequence name
* </li>
* <li>
* Fall back is to use {@value DEF_SEQUENCE}
* </li>
* </ol>
*
* For tables:<ol>
* <li>
* If annotations are used and {@link GeneratedValue#generator()} is specified,
* its value is used as the table name
* </li>
* <li>
* Fall back is to use {@value TableGenerator#DEF_TABLE}
* </li>
* </ol>
*/
public class LegacyNamingStrategy implements ImplicitDatabaseObjectNamingStrategy {
public static final String STRATEGY_NAME = "legacy";
@Override
public QualifiedName determineSequenceName(
Identifier catalogName,
Identifier schemaName,
Map<?, ?> configValues,
ServiceRegistry serviceRegistry) {
final JdbcEnvironment jdbcEnvironment = serviceRegistry.getService( JdbcEnvironment.class );
final String sequenceName = implicitSequenceName( configValues );
if ( sequenceName.contains( "." ) ) {
return QualifiedNameParser.INSTANCE.parse( sequenceName );
}
final JdbcEnvironment jdbcEnvironment = serviceRegistry.getService( JdbcEnvironment.class );
return new QualifiedSequenceName(
catalogName,
schemaName,
jdbcEnvironment.getIdentifierHelper().toIdentifier( DEF_SEQUENCE )
jdbcEnvironment.getIdentifierHelper().toIdentifier( sequenceName )
);
}
private String implicitSequenceName(Map<?, ?> configValues) {
final String explicitSuffix = ConfigurationHelper.getString( CONFIG_SEQUENCE_PER_ENTITY_SUFFIX, configValues );
if ( StringHelper.isNotEmpty( explicitSuffix ) ) {
// an "implicit name suffix" was specified
final String rootTableName = ConfigurationHelper.getString( PersistentIdentifierGenerator.TABLE, configValues );
final String base = ConfigurationHelper.getString( IMPLICIT_NAME_BASE, configValues, rootTableName );
if ( StringHelper.isNotEmpty( base ) ) {
if ( Identifier.isQuoted( base ) ) {
return "`" + Identifier.unQuote( base ) + explicitSuffix + "`";
}
return base + explicitSuffix;
}
}
final String annotationGeneratorName = ConfigurationHelper.getString( IdentifierGenerator.GENERATOR_NAME, configValues );
if ( StringHelper.isNotEmpty( annotationGeneratorName ) ) {
return annotationGeneratorName;
}
return DEF_SEQUENCE;
}
@Override
public QualifiedName determineTableName(
Identifier catalogName,
Identifier schemaName,
Map<?, ?> configValues,
ServiceRegistry serviceRegistry) {
final String implicitName = implicitTableName( configValues );
if ( implicitName.contains( "." ) ) {
return QualifiedNameParser.INSTANCE.parse( implicitName );
}
final JdbcEnvironment jdbcEnvironment = serviceRegistry.getService( JdbcEnvironment.class );
return new QualifiedNameParser.NameParts(
catalogName,
schemaName,
jdbcEnvironment.getIdentifierHelper().toIdentifier( DEF_TABLE )
jdbcEnvironment.getIdentifierHelper().toIdentifier( implicitName )
);
}
private String implicitTableName(Map<?, ?> configValues) {
final String annotationName = ConfigurationHelper.getString( IdentifierGenerator.GENERATOR_NAME, configValues );
if ( StringHelper.isNotEmpty( annotationName ) ) {
return annotationName;
}
return DEF_TABLE;
}
}

View File

@ -1,108 +0,0 @@
/*
* 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 java.util.Map;
import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.boot.model.relational.QualifiedName;
import org.hibernate.boot.model.relational.QualifiedNameParser;
import org.hibernate.boot.model.relational.QualifiedSequenceName;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.id.IdentifierGenerator;
import org.hibernate.id.PersistentIdentifierGenerator;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.internal.util.config.ConfigurationHelper;
import org.hibernate.service.ServiceRegistry;
import static org.hibernate.id.OptimizableGenerator.IMPLICIT_NAME_BASE;
import static org.hibernate.id.enhanced.SequenceStyleGenerator.CONFIG_SEQUENCE_PER_ENTITY_SUFFIX;
import static org.hibernate.id.enhanced.TableGenerator.DEF_TABLE;
/**
* Naming strategy which prefers, for sequences<ol>
* <li>{@link org.hibernate.id.enhanced.TableGenerator#TABLE_PARAM}</li>
* </ol>
*
*
*
* falling back to {@value DEF_SEQUENCE}
*/
public class LegacyPreferGeneratorNameNamingStrategy extends LegacyNamingStrategy {
public static final String STRATEGY_NAME = "prefer-generator-name";
public QualifiedName determineSequenceName(
Identifier catalogName,
Identifier schemaName,
Map<?, ?> configValues,
ServiceRegistry serviceRegistry) {
final String sequenceName = implicitSequenceName( configValues );
if ( sequenceName.contains( "." ) ) {
return QualifiedNameParser.INSTANCE.parse( sequenceName );
}
final JdbcEnvironment jdbcEnvironment = serviceRegistry.getService( JdbcEnvironment.class );
return new QualifiedSequenceName(
catalogName,
schemaName,
jdbcEnvironment.getIdentifierHelper().toIdentifier( sequenceName )
);
}
private String implicitSequenceName(Map<?, ?> configValues) {
final String explicitSuffix = ConfigurationHelper.getString( CONFIG_SEQUENCE_PER_ENTITY_SUFFIX, configValues );
final String rootTableName = ConfigurationHelper.getString( PersistentIdentifierGenerator.TABLE, configValues );
final String base = ConfigurationHelper.getString( IMPLICIT_NAME_BASE, configValues, rootTableName );
if ( StringHelper.isNotEmpty( explicitSuffix ) ) {
// an "implicit name suffix" was specified
if ( StringHelper.isNotEmpty( base ) ) {
if ( Identifier.isQuoted( base ) ) {
return "`" + Identifier.unQuote( base ) + explicitSuffix + "`";
}
return base + explicitSuffix;
}
}
final String annotationGeneratorName = ConfigurationHelper.getString( IdentifierGenerator.GENERATOR_NAME, configValues );
if ( StringHelper.isNotEmpty( annotationGeneratorName ) ) {
return annotationGeneratorName;
}
return DEF_SEQUENCE;
}
@Override
public QualifiedName determineTableName(
Identifier catalogName,
Identifier schemaName,
Map<?, ?> configValues,
ServiceRegistry serviceRegistry) {
final String implicitName = determineImplicitName( configValues );
if ( implicitName.contains( "." ) ) {
return QualifiedNameParser.INSTANCE.parse( implicitName );
}
final JdbcEnvironment jdbcEnvironment = serviceRegistry.getService( JdbcEnvironment.class );
return new QualifiedNameParser.NameParts(
catalogName,
schemaName,
jdbcEnvironment.getIdentifierHelper().toIdentifier( implicitName )
);
}
private String determineImplicitName(Map<?, ?> configValues) {
final String annotationName = ConfigurationHelper.getString( IdentifierGenerator.GENERATOR_NAME, configValues );
if ( StringHelper.isNotEmpty( annotationName ) ) {
return annotationName;
}
return DEF_TABLE;
}
}

View File

@ -339,7 +339,7 @@ public class SequenceStyleGenerator
}
return globalSetting;
},
StandardDatabaseObjectNamingStrategy.class::getName
StandardNamingStrategy.class::getName
);
final ImplicitDatabaseObjectNamingStrategy namingStrategy = strategySelector.resolveStrategy(

View File

@ -0,0 +1,59 @@
/*
* 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 java.util.Map;
import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.boot.model.relational.QualifiedName;
import org.hibernate.boot.model.relational.QualifiedNameParser;
import org.hibernate.boot.model.relational.QualifiedSequenceName;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.service.ServiceRegistry;
import static org.hibernate.id.enhanced.TableGenerator.DEF_TABLE;
/**
* ImplicitDatabaseObjectNamingStrategy using a single structure for
* all implicit names:<ul>
* <li>{@value ImplicitDatabaseObjectNamingStrategy#DEF_SEQUENCE} for sequences</li>
* <li>{@value TableGenerator#DEF_TABLE} for tables</li>
* </ul>
*
* @author Andrea Boriero
*/
public class SingleNamingStrategy implements ImplicitDatabaseObjectNamingStrategy {
public static final String STRATEGY_NAME = "single";
@Override
public QualifiedName determineSequenceName(
Identifier catalogName,
Identifier schemaName,
Map<?, ?> configValues,
ServiceRegistry serviceRegistry) {
final JdbcEnvironment jdbcEnvironment = serviceRegistry.getService( JdbcEnvironment.class );
return new QualifiedSequenceName(
catalogName,
schemaName,
jdbcEnvironment.getIdentifierHelper().toIdentifier( DEF_SEQUENCE )
);
}
public QualifiedName determineTableName(
Identifier catalogName,
Identifier schemaName,
Map<?, ?> configValues,
ServiceRegistry serviceRegistry) {
final JdbcEnvironment jdbcEnvironment = serviceRegistry.getService( JdbcEnvironment.class );
return new QualifiedNameParser.NameParts(
catalogName,
schemaName,
jdbcEnvironment.getIdentifierHelper().toIdentifier( DEF_TABLE )
);
}
}

View File

@ -8,6 +8,8 @@ package org.hibernate.id.enhanced;
import java.util.Map;
import jakarta.persistence.GeneratedValue;
import org.hibernate.MappingException;
import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.boot.model.relational.QualifiedName;
@ -26,10 +28,41 @@ import static org.hibernate.id.enhanced.SequenceStyleGenerator.DEF_SEQUENCE_SUFF
import static org.hibernate.id.enhanced.TableGenerator.DEF_TABLE;
/**
* Hibernate's standard implicit naming strategy for identifier sequences and tables.
*
* For sequences (including forced-table sequences):<ol>
* <li>
* If {@value SequenceStyleGenerator#CONFIG_SEQUENCE_PER_ENTITY_SUFFIX} is specified,
* a name composed of the "base" name with the specified suffix. The base name
* depends on the usage of the generator, but is generally the root entity-name if
* applied to an entity identifier or the table we are generating values for
* </li>
* <li>
* If annotations are used and {@link GeneratedValue#generator()} is specified,
* its value is used as the sequence name
* </li>
* <li>
* If the "base" name is known, use that
* </li>
* <li>
* Throw an exception
* </li>
* </ol>
*
* For tables:<ol>
* <li>
* If annotations are used and {@link GeneratedValue#generator()} is specified,
* its value is used as the table name
* </li>
* <li>
* Fall back is to use {@value TableGenerator#DEF_TABLE}
* </li>
* </ol>
*
* @author Steve Ebersole
*/
public class StandardDatabaseObjectNamingStrategy implements ImplicitDatabaseObjectNamingStrategy {
public static final String STRATEGY_NAME = "default";
public class StandardNamingStrategy implements ImplicitDatabaseObjectNamingStrategy {
public static final String STRATEGY_NAME = "standard";
@Override
public QualifiedName determineSequenceName(
@ -40,7 +73,7 @@ public class StandardDatabaseObjectNamingStrategy implements ImplicitDatabaseObj
final JdbcEnvironment jdbcEnvironment = serviceRegistry.getService( JdbcEnvironment.class );
final String rootTableName = ConfigurationHelper.getString( PersistentIdentifierGenerator.TABLE, configValues );
final String implicitName = implicitName( rootTableName, configValues, serviceRegistry );
final String implicitName = implicitSequenceName( rootTableName, configValues, serviceRegistry );
if ( implicitName.contains( "." ) ) {
return QualifiedNameParser.INSTANCE.parse( implicitName );
@ -53,7 +86,7 @@ public class StandardDatabaseObjectNamingStrategy implements ImplicitDatabaseObj
);
}
private static String implicitName(
private static String implicitSequenceName(
String rootTableName,
Map<?, ?> configValues,
ServiceRegistry serviceRegistry) {

View File

@ -411,7 +411,7 @@ public class TableGenerator implements PersistentIdentifierGenerator {
}
return globalSetting;
},
StandardDatabaseObjectNamingStrategy.class::getName
StandardNamingStrategy.class::getName
);
final ImplicitDatabaseObjectNamingStrategy namingStrategy = strategySelector.resolveStrategy(

View File

@ -4,7 +4,7 @@
* 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.namingstrategy;
package org.hibernate.orm.test.id.enhanced;
import java.util.Map;
import jakarta.persistence.Basic;
@ -41,11 +41,11 @@ import static org.assertj.core.api.Assertions.assertThat;
@org.hibernate.testing.orm.junit.ServiceRegistry(
settings = @Setting(
name = AvailableSettings.ID_DB_STRUCTURE_NAMING_STRATEGY,
value = "org.hibernate.orm.test.namingstrategy.ImplicitDatabaseObjectNamingStrategyTests$Strategy"
value = "org.hibernate.orm.test.id.enhanced.CustomNamingStrategyTests$Strategy"
)
)
@DomainModel( annotatedClasses = ImplicitDatabaseObjectNamingStrategyTests.TheEntity.class )
public class ImplicitDatabaseObjectNamingStrategyTests {
@DomainModel( annotatedClasses = CustomNamingStrategyTests.TheEntity.class )
public class CustomNamingStrategyTests {
@Test
public void testIt(DomainModelScope domainModelScope, ServiceRegistryScope serviceRegistryScope) {

View File

@ -0,0 +1,47 @@
/*
* 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.enhanced;
import org.hibernate.boot.registry.selector.spi.StrategySelector;
import org.hibernate.id.enhanced.ImplicitDatabaseObjectNamingStrategy;
import org.hibernate.id.enhanced.LegacyNamingStrategy;
import org.hibernate.id.enhanced.SingleNamingStrategy;
import org.hibernate.id.enhanced.StandardNamingStrategy;
import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.ServiceRegistryScope;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Steve Ebersole
*/
@ServiceRegistry
public class NamingStrategySelectorTests {
@Test
void testShortNames(ServiceRegistryScope scope) {
scope.withService( StrategySelector.class, (service) -> {
final ImplicitDatabaseObjectNamingStrategy single = service.resolveStrategy( ImplicitDatabaseObjectNamingStrategy.class, SingleNamingStrategy.STRATEGY_NAME );
assertThat( single ).isInstanceOf( SingleNamingStrategy.class );
final ImplicitDatabaseObjectNamingStrategy legacy = service.resolveStrategy( ImplicitDatabaseObjectNamingStrategy.class, LegacyNamingStrategy.STRATEGY_NAME );
assertThat( legacy ).isInstanceOf( LegacyNamingStrategy.class );
final ImplicitDatabaseObjectNamingStrategy standard = service.resolveStrategy( ImplicitDatabaseObjectNamingStrategy.class, StandardNamingStrategy.STRATEGY_NAME );
assertThat( standard ).isInstanceOf( StandardNamingStrategy.class );
} );
}
@Test
void testMissing(ServiceRegistryScope scope) {
scope.withService( StrategySelector.class, (service) -> {
final ImplicitDatabaseObjectNamingStrategy single = service.resolveStrategy( ImplicitDatabaseObjectNamingStrategy.class, null );
assertThat( single ).isNull();
} );
}
}

View File

@ -22,10 +22,10 @@ import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.id.IdentifierGenerator;
import org.hibernate.id.enhanced.LegacyNamingStrategy;
import org.hibernate.id.enhanced.LegacyPreferGeneratorNameNamingStrategy;
import org.hibernate.id.enhanced.SingleNamingStrategy;
import org.hibernate.id.enhanced.SequenceStructure;
import org.hibernate.id.enhanced.SequenceStyleGenerator;
import org.hibernate.id.enhanced.StandardDatabaseObjectNamingStrategy;
import org.hibernate.id.enhanced.StandardNamingStrategy;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.service.ServiceRegistry;
@ -44,77 +44,77 @@ public class SequenceNamingStrategyTest {
@Test
public void testSequenceNameStandardStrategy() {
verify( TestEntity.class, "TestEntity_SEQ" );
verify( TestEntity.class, StandardDatabaseObjectNamingStrategy.STRATEGY_NAME, "TestEntity_SEQ" );
verify( TestEntity.class, StandardDatabaseObjectNamingStrategy.class.getName(), "TestEntity_SEQ" );
verify( TestEntity.class, StandardNamingStrategy.STRATEGY_NAME, "TestEntity_SEQ" );
verify( TestEntity.class, StandardNamingStrategy.class.getName(), "TestEntity_SEQ" );
}
@Test
public void testSequenceNameHibernateSequenceStrategy() {
verify( TestEntity.class, SingleNamingStrategy.STRATEGY_NAME, "hibernate_sequence" );
verify( TestEntity.class, SingleNamingStrategy.class.getName(), "hibernate_sequence" );
}
@Test
public void testSequenceNamePreferGeneratorNameStrategy() {
verify( TestEntity.class, LegacyNamingStrategy.STRATEGY_NAME, "hibernate_sequence" );
verify( TestEntity.class, LegacyNamingStrategy.class.getName(), "hibernate_sequence" );
}
@Test
public void testSequenceNamePreferGeneratorNameStrategy() {
verify( TestEntity.class, LegacyPreferGeneratorNameNamingStrategy.STRATEGY_NAME, "hibernate_sequence" );
verify( TestEntity.class, LegacyPreferGeneratorNameNamingStrategy.class.getName(), "hibernate_sequence" );
}
@Test
public void testNoGeneratorStandardStrategy() {
verify( TestEntity2.class, "table_generator" );
verify( TestEntity2.class, StandardDatabaseObjectNamingStrategy.STRATEGY_NAME, "table_generator" );
verify( TestEntity2.class, StandardDatabaseObjectNamingStrategy.class.getName(), "table_generator" );
verify( TestEntity2.class, StandardNamingStrategy.STRATEGY_NAME, "table_generator" );
verify( TestEntity2.class, StandardNamingStrategy.class.getName(), "table_generator" );
}
@Test
public void testNoGeneratorHibernateSequenceStrategy() {
verify( TestEntity2.class, LegacyNamingStrategy.STRATEGY_NAME, "hibernate_sequence" );
verify( TestEntity2.class, LegacyNamingStrategy.class.getName(), "hibernate_sequence" );
verify( TestEntity2.class, SingleNamingStrategy.STRATEGY_NAME, "hibernate_sequence" );
verify( TestEntity2.class, SingleNamingStrategy.class.getName(), "hibernate_sequence" );
}
@Test
public void testNoGeneratorPreferGeneratorNameStrategy() {
verify( TestEntity2.class, LegacyPreferGeneratorNameNamingStrategy.STRATEGY_NAME, "table_generator" );
verify( TestEntity2.class, LegacyPreferGeneratorNameNamingStrategy.class.getName(), "table_generator" );
verify( TestEntity2.class, LegacyNamingStrategy.STRATEGY_NAME, "table_generator" );
verify( TestEntity2.class, LegacyNamingStrategy.class.getName(), "table_generator" );
}
@Test
public void testGeneratorWithoutSequenceNameStandardStrategy() {
verify( TestEntity3.class, "table_generator" );
verify( TestEntity3.class, StandardDatabaseObjectNamingStrategy.STRATEGY_NAME, "table_generator" );
verify( TestEntity3.class, StandardDatabaseObjectNamingStrategy.class.getName(), "table_generator" );
verify( TestEntity3.class, StandardNamingStrategy.STRATEGY_NAME, "table_generator" );
verify( TestEntity3.class, StandardNamingStrategy.class.getName(), "table_generator" );
}
@Test
public void testGeneratorWithoutSequenceNameHibernateSequenceStrategy() {
verify( TestEntity3.class, LegacyNamingStrategy.STRATEGY_NAME, "hibernate_sequence" );
verify( TestEntity3.class, LegacyNamingStrategy.class.getName(), "hibernate_sequence" );
verify( TestEntity3.class, SingleNamingStrategy.STRATEGY_NAME, "hibernate_sequence" );
verify( TestEntity3.class, SingleNamingStrategy.class.getName(), "hibernate_sequence" );
}
@Test
public void testGeneratorWithoutSequenceNamePreferGeneratorNameStrategy() {
verify( TestEntity3.class, LegacyPreferGeneratorNameNamingStrategy.STRATEGY_NAME, "table_generator" );
verify( TestEntity3.class, LegacyPreferGeneratorNameNamingStrategy.class.getName(), "table_generator" );
verify( TestEntity3.class, LegacyNamingStrategy.STRATEGY_NAME, "table_generator" );
verify( TestEntity3.class, LegacyNamingStrategy.class.getName(), "table_generator" );
}
@Test
public void testGeneratorWithSequenceNameStandardStrategy() throws Exception {
verify( TestEntity4.class, "test_sequence" );
verify( TestEntity4.class, StandardDatabaseObjectNamingStrategy.STRATEGY_NAME, "test_sequence" );
verify( TestEntity4.class, StandardDatabaseObjectNamingStrategy.class.getName(), "test_sequence" );
verify( TestEntity4.class, StandardNamingStrategy.STRATEGY_NAME, "test_sequence" );
verify( TestEntity4.class, StandardNamingStrategy.class.getName(), "test_sequence" );
}
@Test
public void testGeneratorWithSequenceNameHibernateSequenceStrategy() {
verify( TestEntity4.class, LegacyNamingStrategy.STRATEGY_NAME, "test_sequence" );
verify( TestEntity4.class, LegacyNamingStrategy.class.getName(), "test_sequence" );
verify( TestEntity4.class, SingleNamingStrategy.STRATEGY_NAME, "test_sequence" );
verify( TestEntity4.class, SingleNamingStrategy.class.getName(), "test_sequence" );
}
@Test
public void testGeneratorWithSequenceNamePreferGeneratorNameStrategy() throws Exception {
verify( TestEntity4.class, LegacyPreferGeneratorNameNamingStrategy.STRATEGY_NAME, "test_sequence" );
verify( TestEntity4.class, LegacyPreferGeneratorNameNamingStrategy.class.getName(), "test_sequence" );
verify( TestEntity4.class, LegacyNamingStrategy.STRATEGY_NAME, "test_sequence" );
verify( TestEntity4.class, LegacyNamingStrategy.class.getName(), "test_sequence" );
}
private void verify(Class<?> entityType, String expectedName) {

View File

@ -9,7 +9,6 @@ package org.hibernate.orm.test.id.enhanced;
import java.util.function.Consumer;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.TableGenerator;
@ -21,8 +20,8 @@ import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.id.IdentifierGenerator;
import org.hibernate.id.enhanced.LegacyNamingStrategy;
import org.hibernate.id.enhanced.LegacyPreferGeneratorNameNamingStrategy;
import org.hibernate.id.enhanced.StandardDatabaseObjectNamingStrategy;
import org.hibernate.id.enhanced.SingleNamingStrategy;
import org.hibernate.id.enhanced.StandardNamingStrategy;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Table;
import org.hibernate.service.ServiceRegistry;
@ -87,18 +86,18 @@ public class TableNamingStrategyTest {
private void verifyStandardStrategy(Class<?> entityClass, String expectedName) {
verify( entityClass, expectedName );
verify( entityClass, StandardDatabaseObjectNamingStrategy.STRATEGY_NAME, expectedName );
verify( entityClass, StandardDatabaseObjectNamingStrategy.class.getName(), expectedName );
verify( entityClass, StandardNamingStrategy.STRATEGY_NAME, expectedName );
verify( entityClass, StandardNamingStrategy.class.getName(), expectedName );
}
private void verifyLegacyStrategy(Class<?> entityClass, String expectedName) {
verify( entityClass, LegacyNamingStrategy.STRATEGY_NAME, expectedName );
verify( entityClass, LegacyNamingStrategy.class.getName(), expectedName );
verify( entityClass, SingleNamingStrategy.STRATEGY_NAME, expectedName );
verify( entityClass, SingleNamingStrategy.class.getName(), expectedName );
}
private void verifyLegacyPreferStrategy(Class<?> entityClass, String expectedName) {
verify( entityClass, LegacyPreferGeneratorNameNamingStrategy.STRATEGY_NAME, expectedName );
verify( entityClass, LegacyPreferGeneratorNameNamingStrategy.class.getName(), expectedName );
verify( entityClass, LegacyNamingStrategy.STRATEGY_NAME, expectedName );
verify( entityClass, LegacyNamingStrategy.class.getName(), expectedName );
}
private void verify(Class<?> entityType, String expectedName) {

View File

@ -99,22 +99,20 @@ to define custom generators to use for identifier generation.
// todo (6.0 - @Steve - need to add content about this to the User Guide
[[id-sequence-generation]]
== Id Sequence and Table generation
[[id-sequence-table-name]]
== Implicit Identifier Sequence and Table Name
For a sequence id generation strategy Hibernate 6.0 by default does not create anymore a single sequence named `hibernate_sequence` but it creates one sequence for each entity.
The way in which Hibernate determines implicit names for sequences and tables associated with identifier
generation has changed in 6.0 which may affect migrating applications.
In order to maintain backward compatibility a new setting `hibernate.id.db_structure_naming_strategy`
has been introduced.
To help with backwards compatibility, or to apply any general naming strategy, 6.0 introduces the
`org.hibernate.id.enhanced.ImplicitDatabaseObjectNamingStrategy` contract which can be specified using
the `hibernate.id.db_structure_naming_strategy` setting. See discussion at
link:{javadocsBase}/org/hibernate/cfg/AvailableSettings.html#ID_DB_STRUCTURE_NAMING_STRATEGY
For backwards compatibility, use either `hibernate.id.db_structure_naming_strategy=single` or
`hibernate.id.db_structure_naming_strategy=legacy` depending on needs
In case the code has a generator name with no matching generator or with a generator not specifying a sequence or table name
and the property `hibernate.model.generator_name_as_sequence_name` is not set to `false` then to maintain the backward compatibility is necessary to set
hibernate.id.db_structure_naming_strategy=org.hibernate.id.enhanced.LegacyPreferGeneratorNameNamingStrategy
```
otherwise
```
hibernate.id.db_structure_naming_strategy=org.hibernate.id.enhanced.LegacyNamingStrategy
```
[[type]]
== Type system