Skip to content

HHH-19484 make it easier to customize ImplicitNamingStrategyJpaCompliantImpl #10172

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 26, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -159,10 +159,11 @@ private void createIndexOrUniqueKey(
String[] columnNames,
String[] orderings,
boolean unique,
boolean declaredAsIndex,
String options,
Selectable[] columns) {
final IndexOrUniqueKeyNameSource source =
new IndexOrUniqueKeyNameSource( context, table, columnNames, originalKeyName );
new IndexOrUniqueKeyNameSource( context, table, columnNames, originalKeyName, declaredAsIndex );
boolean hasFormula = false;
for ( Selectable selectable : columns ) {
if ( selectable.isFormula() ) {
Expand Down Expand Up @@ -218,6 +219,7 @@ void bindIndexes(Table table, jakarta.persistence.Index[] indexes) {
columnExpressions,
ordering,
unique,
true,
options,
selectables( table, name, columnExpressions )
);
Expand All @@ -236,6 +238,7 @@ void bindUniqueConstraints(Table table, UniqueConstraint[] constraints) {
columnNames,
null,
true,
false,
options,
columns( table, name, columnNames )
);
Expand All @@ -261,17 +264,32 @@ else if ( tmp.endsWith( " asc" ) ) {
}
}

private class IndexOrUniqueKeyNameSource implements ImplicitIndexNameSource, ImplicitUniqueKeyNameSource {
private class IndexOrUniqueKeyNameSource
implements ImplicitIndexNameSource, ImplicitUniqueKeyNameSource {
private final MetadataBuildingContext buildingContext;
private final Table table;
private final String[] columnNames;
private final String originalKeyName;
private final boolean declaredAsIndex;

public IndexOrUniqueKeyNameSource(MetadataBuildingContext buildingContext, Table table, String[] columnNames, String originalKeyName) {
private IndexOrUniqueKeyNameSource(
MetadataBuildingContext buildingContext,
Table table,
String[] columnNames,
String originalKeyName,
boolean declaredAsIndex) {
this.buildingContext = buildingContext;
this.table = table;
this.columnNames = columnNames;
this.originalKeyName = originalKeyName;
this.declaredAsIndex = declaredAsIndex;
}

@Override
public Kind kind() {
return declaredAsIndex
? ImplicitIndexNameSource.super.kind()
: ImplicitUniqueKeyNameSource.super.kind();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,17 @@
*
* @author Steve Ebersole
*/
public interface ImplicitConstraintNameSource extends ImplicitNameSource {
public sealed interface ImplicitConstraintNameSource
extends ImplicitNameSource
permits ImplicitIndexNameSource, ImplicitUniqueKeyNameSource, ImplicitForeignKeyNameSource {
Identifier getTableName();
List<Identifier> getColumnNames();
Identifier getUserProvidedIdentifier();
Kind kind();

enum Kind {
FOREIGN_KEY,
UNIQUE_KEY,
INDEX
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,13 @@
/**
* @author Steve Ebersole
*/
public interface ImplicitForeignKeyNameSource extends ImplicitConstraintNameSource {
public non-sealed interface ImplicitForeignKeyNameSource
extends ImplicitConstraintNameSource {
Identifier getReferencedTableName();
List<Identifier> getReferencedColumnNames();

@Override
default Kind kind() {
return Kind.FOREIGN_KEY;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,10 @@
/**
* @author Steve Ebersole
*/
public interface ImplicitIndexNameSource extends ImplicitConstraintNameSource {
public non-sealed interface ImplicitIndexNameSource
extends ImplicitConstraintNameSource {
@Override
default Kind kind() {
return Kind.INDEX;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import org.hibernate.HibernateException;
import org.hibernate.boot.model.source.spi.AttributePath;
import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.engine.jdbc.env.spi.IdentifierHelper;

import static org.hibernate.boot.model.naming.ImplicitJoinColumnNameSource.Nature.ELEMENT_COLLECTION;
import static org.hibernate.internal.util.StringHelper.isNotEmpty;
Expand Down Expand Up @@ -92,17 +93,19 @@ public Identifier determineIdentifierColumnName(ImplicitIdentifierColumnNameSour

@Override
public Identifier determineDiscriminatorColumnName(ImplicitDiscriminatorColumnNameSource source) {
final MetadataBuildingContext context = source.getBuildingContext();
return toIdentifier(
source.getBuildingContext().getEffectiveDefaults().getDefaultDiscriminatorColumnName(),
source.getBuildingContext()
context.getEffectiveDefaults().getDefaultDiscriminatorColumnName(),
context
);
}

@Override
public Identifier determineTenantIdColumnName(ImplicitTenantIdColumnNameSource source) {
final MetadataBuildingContext context = source.getBuildingContext();
return toIdentifier(
source.getBuildingContext().getEffectiveDefaults().getDefaultTenantIdColumnName(),
source.getBuildingContext()
context.getEffectiveDefaults().getDefaultTenantIdColumnName(),
context
);
}

Expand All @@ -113,7 +116,10 @@ public Identifier determineTenantIdColumnName(ImplicitTenantIdColumnNameSource s
*/
@Override
public Identifier determineBasicColumnName(ImplicitBasicColumnNameSource source) {
return toIdentifier( transformAttributePath( source.getAttributePath() ), source.getBuildingContext() );
return toIdentifier(
transformAttributePath( source.getAttributePath() ),
source.getBuildingContext()
);
}

/**
Expand Down Expand Up @@ -152,25 +158,24 @@ public Identifier determinePrimaryKeyJoinColumnName(ImplicitPrimaryKeyJoinColumn

@Override
public Identifier determineAnyDiscriminatorColumnName(ImplicitAnyDiscriminatorColumnNameSource source) {
final MetadataBuildingContext buildingContext = source.getBuildingContext();
final MetadataBuildingContext context = source.getBuildingContext();
return toIdentifier(
transformAttributePath( source.getAttributePath() )
+ "_" + buildingContext.getEffectiveDefaults().getDefaultDiscriminatorColumnName(),
buildingContext
+ "_" + context.getEffectiveDefaults().getDefaultDiscriminatorColumnName(),
context
);
}

@Override
public Identifier determineAnyKeyColumnName(ImplicitAnyKeyColumnNameSource source) {
final MetadataBuildingContext buildingContext = source.getBuildingContext();
final MetadataBuildingContext context = source.getBuildingContext();
return toIdentifier(
transformAttributePath( source.getAttributePath() )
+ "_" + buildingContext.getEffectiveDefaults().getDefaultIdColumnName(),
buildingContext
+ "_" + context.getEffectiveDefaults().getDefaultIdColumnName(),
context
);
}


@Override
public Identifier determineMapKeyColumnName(ImplicitMapKeyColumnNameSource source) {
return toIdentifier(
Expand All @@ -190,35 +195,25 @@ public Identifier determineListIndexColumnName(ImplicitIndexColumnNameSource sou
@Override
public Identifier determineForeignKeyName(ImplicitForeignKeyNameSource source) {
final Identifier userProvidedIdentifier = source.getUserProvidedIdentifier();
final MetadataBuildingContext buildingContext = source.getBuildingContext();
return userProvidedIdentifier != null ? userProvidedIdentifier : toIdentifier(
NamingHelper.withCharset( buildingContext.getBuildingOptions().getSchemaCharset() )
.generateHashedFkName( "FK", source.getTableName(),
source.getReferencedTableName(), source.getColumnNames() ),
buildingContext
);
return userProvidedIdentifier == null
? generateConstraintName( source )
: userProvidedIdentifier;
}

@Override
public Identifier determineUniqueKeyName(ImplicitUniqueKeyNameSource source) {
final Identifier userProvidedIdentifier = source.getUserProvidedIdentifier();
final MetadataBuildingContext buildingContext = source.getBuildingContext();
return userProvidedIdentifier != null ? userProvidedIdentifier : toIdentifier(
NamingHelper.withCharset( buildingContext.getBuildingOptions().getSchemaCharset() )
.generateHashedConstraintName( "UK", source.getTableName(), source.getColumnNames() ),
buildingContext
);
return userProvidedIdentifier == null
? generateConstraintName( source )
: userProvidedIdentifier;
}

@Override
public Identifier determineIndexName(ImplicitIndexNameSource source) {
final Identifier userProvidedIdentifier = source.getUserProvidedIdentifier();
final MetadataBuildingContext buildingContext = source.getBuildingContext();
return userProvidedIdentifier != null ? userProvidedIdentifier : toIdentifier(
NamingHelper.withCharset( buildingContext.getBuildingOptions().getSchemaCharset() )
.generateHashedConstraintName( "IDX", source.getTableName(), source.getColumnNames() ),
buildingContext
);
return userProvidedIdentifier == null
? generateConstraintName( source )
: userProvidedIdentifier;
}

/**
Expand All @@ -235,18 +230,85 @@ protected String transformAttributePath(AttributePath attributePath) {
}

/**
* Easy hook to build an Identifier using the keyword safe IdentifierHelper.
* Easy hook to build an {@link Identifier} using the keyword safe
* {@link org.hibernate.engine.jdbc.env.spi.IdentifierHelper}.
*
* @param stringForm The String form of the name
* @param buildingContext Access to the IdentifierHelper
* @param buildingContext Access to the {@code IdentifierHelper}
*
* @return The identifier
*/
protected Identifier toIdentifier(String stringForm, MetadataBuildingContext buildingContext) {
return buildingContext.getMetadataCollector()
.getDatabase()
.getJdbcEnvironment()
.getIdentifierHelper()
.toIdentifier( stringForm );
return toIdentifier( stringForm,
buildingContext.getMetadataCollector()
.getDatabase()
.getJdbcEnvironment()
.getIdentifierHelper() );
}

/**
* Easy hook to build an {@link Identifier} using the keyword safe
* {@link org.hibernate.engine.jdbc.env.spi.IdentifierHelper}.
*
* @param stringForm The String form of the name
* @param identifierHelper The {@code IdentifierHelper}
*
* @return The identifier
*/
protected Identifier toIdentifier(String stringForm, IdentifierHelper identifierHelper) {
return identifierHelper.toIdentifier( stringForm );
}

/**
* Generate a name for the given constraint.
*
* @return The identifier
*/
protected Identifier generateConstraintName(ImplicitConstraintNameSource source) {
return toIdentifier( generateConstraintNameString( source ), source.getBuildingContext() );
}

/**
* Generate a name for the given constraint.
*
* @return The name as a string
*/
protected String generateConstraintNameString(ImplicitConstraintNameSource source) {
final NamingHelper namingHelper = namingHelper( source.getBuildingContext() );
final String prefix = constraintNamePrefix( source.kind() );
return source instanceof ImplicitForeignKeyNameSource foreignKeySource
? namingHelper.generateHashedFkName(
prefix,
source.getTableName(),
// include the referenced table in the hash
foreignKeySource.getReferencedTableName(),
source.getColumnNames()
)
: namingHelper.generateHashedConstraintName(
prefix,
source.getTableName(),
source.getColumnNames()
);
}

/**
* Obtain a {@link NamingHelper} for use in constraint name generation.
*/
protected NamingHelper namingHelper(MetadataBuildingContext context) {
return NamingHelper.withCharset( context.getBuildingOptions().getSchemaCharset() );
}

/**
* The prefix for a generated constraint name of the given
* {@linkplain ImplicitConstraintNameSource.Kind kind}.
*
* @return The prefix as a string
*/
protected String constraintNamePrefix(ImplicitConstraintNameSource.Kind kind) {
return switch ( kind ) {
case INDEX -> "IDX";
case UNIQUE_KEY -> "UK";
case FOREIGN_KEY -> "FK";
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*/
package org.hibernate.boot.model.naming;

import org.hibernate.internal.util.StringHelper;
import static org.hibernate.internal.util.StringHelper.unqualify;

/**
* Implements the original legacy naming behavior.
Expand All @@ -19,7 +19,7 @@ public class ImplicitNamingStrategyLegacyHbmImpl extends ImplicitNamingStrategyJ

@Override
protected String transformEntityName(EntityNaming entityNaming) {
return StringHelper.unqualify( entityNaming.getEntityName() );
return unqualify( entityNaming.getEntityName() );
}

@Override
Expand All @@ -37,21 +37,21 @@ public Identifier determineJoinColumnName(ImplicitJoinColumnNameSource source) {
source.getBuildingContext()
);
}

return super.determineJoinColumnName( source );
else {
return super.determineJoinColumnName( source );
}
}


@Override
public Identifier determineJoinTableName(ImplicitJoinTableNameSource source) {
if ( source.getAssociationOwningAttributePath() != null ) {
final String name = source.getOwningPhysicalTableName()
+ '_'
+ transformAttributePath( source.getAssociationOwningAttributePath() );

return toIdentifier( name, source.getBuildingContext() );
}

return super.determineJoinTableName( source );
else {
return super.determineJoinTableName( source );
}
}
}
Loading
Loading