HHH-16985 use ImplicitNamingStrategy in a much more disciplined way

for generating constraint names
This commit is contained in:
Gavin King 2024-03-11 11:22:33 +01:00
parent 9c12ea8b11
commit da9d2c2bf7
31 changed files with 455 additions and 293 deletions

View File

@ -0,0 +1,81 @@
/*
* 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.boot.internal;
import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.boot.model.naming.ImplicitForeignKeyNameSource;
import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.mapping.Column;
import org.hibernate.mapping.ForeignKey;
import org.hibernate.mapping.Table;
import java.util.List;
import static java.util.Collections.emptyList;
import static org.hibernate.internal.util.collections.CollectionHelper.arrayList;
public class ForeignKeyNameSource implements ImplicitForeignKeyNameSource {
final List<Identifier> columnNames;
private final ForeignKey foreignKey;
private final Table table;
private final MetadataBuildingContext buildingContext;
List<Identifier> referencedColumnNames;
public ForeignKeyNameSource(ForeignKey foreignKey, Table table, MetadataBuildingContext buildingContext) {
this.foreignKey = foreignKey;
this.table = table;
this.buildingContext = buildingContext;
columnNames = extractColumnNames(foreignKey.getColumns());
referencedColumnNames = null;
}
@Override
public Identifier getTableName() {
return table.getNameIdentifier();
}
@Override
public List<Identifier> getColumnNames() {
return columnNames;
}
@Override
public Identifier getReferencedTableName() {
return foreignKey.getReferencedTable().getNameIdentifier();
}
@Override
public List<Identifier> getReferencedColumnNames() {
if ( referencedColumnNames == null ) {
referencedColumnNames = extractColumnNames( foreignKey.getReferencedColumns() );
}
return referencedColumnNames;
}
@Override
public Identifier getUserProvidedIdentifier() {
return foreignKey.getName() != null ? Identifier.toIdentifier(foreignKey.getName()) : null;
}
@Override
public MetadataBuildingContext getBuildingContext() {
return buildingContext;
}
private List<Identifier> extractColumnNames(List<Column> columns) {
if ( columns == null || columns.isEmpty() ) {
return emptyList();
}
final List<Identifier> columnNames = arrayList( columns.size() );
for ( Column column : columns ) {
columnNames.add( column.getNameIdentifier( buildingContext ) );
}
return columnNames;
}
}

View File

@ -53,7 +53,6 @@
import org.hibernate.boot.model.internal.SecondaryTableSecondPass; import org.hibernate.boot.model.internal.SecondaryTableSecondPass;
import org.hibernate.boot.model.internal.SetBasicValueTypeSecondPass; import org.hibernate.boot.model.internal.SetBasicValueTypeSecondPass;
import org.hibernate.boot.model.naming.Identifier; import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.boot.model.naming.ImplicitForeignKeyNameSource;
import org.hibernate.boot.model.relational.AuxiliaryDatabaseObject; import org.hibernate.boot.model.relational.AuxiliaryDatabaseObject;
import org.hibernate.boot.model.relational.Database; import org.hibernate.boot.model.relational.Database;
import org.hibernate.boot.model.relational.ExportableProducer; import org.hibernate.boot.model.relational.ExportableProducer;
@ -111,9 +110,6 @@
import jakarta.persistence.Entity; import jakarta.persistence.Entity;
import jakarta.persistence.MapsId; import jakarta.persistence.MapsId;
import static java.util.Collections.emptyList;
import static org.hibernate.internal.util.collections.CollectionHelper.arrayList;
/** /**
* The implementation of the {@linkplain InFlightMetadataCollector in-flight * The implementation of the {@linkplain InFlightMetadataCollector in-flight
* metadata collector contract}. * metadata collector contract}.
@ -1935,24 +1931,14 @@ private void secondPassCompileForeignKeys(MetadataBuildingContext buildingContex
protected void secondPassCompileForeignKeys(Table table, Set<ForeignKey> done, MetadataBuildingContext buildingContext) protected void secondPassCompileForeignKeys(Table table, Set<ForeignKey> done, MetadataBuildingContext buildingContext)
throws MappingException { throws MappingException {
table.createForeignKeys(); table.createForeignKeys( buildingContext );
final Dialect dialect = getDatabase().getJdbcEnvironment().getDialect(); final Dialect dialect = getDatabase().getJdbcEnvironment().getDialect();
for ( ForeignKey foreignKey : table.getForeignKeys().values() ) { for ( ForeignKey foreignKey : table.getForeignKeys().values() ) {
if ( !done.contains( foreignKey ) ) { if ( !done.contains( foreignKey ) ) {
done.add( foreignKey ); done.add( foreignKey );
final String referencedEntityName = foreignKey.getReferencedEntityName(); final PersistentClass referencedClass = foreignKey.resolveReferencedClass(this);
if ( referencedEntityName == null ) {
throw new MappingException( "An association from the table '" + foreignKey.getTable().getName() +
"' does not specify the referenced entity" );
}
log.debugf( "Resolving reference to class: %s", referencedEntityName );
final PersistentClass referencedClass = getEntityBinding( referencedEntityName );
if ( referencedClass == null ) {
throw new MappingException( "An association from the table '" + foreignKey.getTable().getName() +
"' refers to an unmapped class '" + referencedEntityName + "'" );
}
if ( referencedClass.isJoinedSubclass() ) { if ( referencedClass.isJoinedSubclass() ) {
secondPassCompileForeignKeys( referencedClass.getSuperclass().getTable(), done, buildingContext); secondPassCompileForeignKeys( referencedClass.getSuperclass().getTable(), done, buildingContext);
} }
@ -1971,19 +1957,6 @@ protected void secondPassCompileForeignKeys(Table table, Set<ForeignKey> done, M
} }
} }
private List<Identifier> extractColumnNames(List<Column> columns) {
if ( columns == null || columns.isEmpty() ) {
return emptyList();
}
final List<Identifier> columnNames = arrayList( columns.size() );
for ( Column column : columns ) {
columnNames.add( getDatabase().toIdentifier( column.getQuotedName() ) );
}
return columnNames;
}
private void processPropertyReferences() { private void processPropertyReferences() {
if ( delayedPropertyReferenceHandlers == null ) { if ( delayedPropertyReferenceHandlers == null ) {
return; return;
@ -2173,53 +2146,4 @@ private void handleIdentifierValueBinding(
log.debugf( "Ignoring exception thrown when trying to build IdentifierGenerator as part of Metadata building", e ); log.debugf( "Ignoring exception thrown when trying to build IdentifierGenerator as part of Metadata building", e );
} }
} }
private class ForeignKeyNameSource implements ImplicitForeignKeyNameSource {
final List<Identifier> columnNames;
private final ForeignKey foreignKey;
private final Table table;
private final MetadataBuildingContext buildingContext;
List<Identifier> referencedColumnNames;
public ForeignKeyNameSource(ForeignKey foreignKey, Table table, MetadataBuildingContext buildingContext) {
this.foreignKey = foreignKey;
this.table = table;
this.buildingContext = buildingContext;
columnNames = extractColumnNames(foreignKey.getColumns());
referencedColumnNames = null;
}
@Override
public Identifier getTableName() {
return table.getNameIdentifier();
}
@Override
public List<Identifier> getColumnNames() {
return columnNames;
}
@Override
public Identifier getReferencedTableName() {
return foreignKey.getReferencedTable().getNameIdentifier();
}
@Override
public List<Identifier> getReferencedColumnNames() {
if ( referencedColumnNames == null ) {
referencedColumnNames = extractColumnNames( foreignKey.getReferencedColumns() );
}
return referencedColumnNames;
}
@Override
public Identifier getUserProvidedIdentifier() {
return foreignKey.getName() != null ? Identifier.toIdentifier( foreignKey.getName() ) : null;
}
@Override
public MetadataBuildingContext getBuildingContext() {
return buildingContext;
}
}
} }

View File

@ -301,7 +301,9 @@ protected void initMappingColumn(
mappingColumn.setArrayLength( arrayLength ); mappingColumn.setArrayLength( arrayLength );
mappingColumn.setNullable( nullable ); mappingColumn.setNullable( nullable );
mappingColumn.setSqlType( sqlType ); mappingColumn.setSqlType( sqlType );
mappingColumn.setUnique( unique ); if ( unique ) {
getParent().getTable().createUniqueKey( mappingColumn, getBuildingContext() );
}
for ( CheckConstraint constraint : checkConstraints ) { for ( CheckConstraint constraint : checkConstraints ) {
mappingColumn.addCheckConstraint( constraint ); mappingColumn.addCheckConstraint( constraint );
} }

View File

@ -610,7 +610,8 @@ public Identifier getReferencedColumnName() {
) )
); );
} }
return database.toIdentifier( ( (Column) selectable ).getQuotedName() ); final Column column = (Column) selectable;
return column.getNameIdentifier( getBuildingContext() );
} }
@Override @Override

View File

@ -350,7 +350,7 @@ private static Property makeSyntheticComponentProperty(
else { else {
ownerEntity.addProperty( result ); ownerEntity.addProperty( result );
} }
embeddedComponent.createUniqueKey(); //make it unique embeddedComponent.createUniqueKey( context ); //make it unique
return result; return result;
} }

View File

@ -8,10 +8,7 @@
import jakarta.persistence.UniqueConstraint; import jakarta.persistence.UniqueConstraint;
import org.hibernate.AnnotationException; import org.hibernate.AnnotationException;
import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.boot.model.naming.ImplicitIndexNameSource;
import org.hibernate.boot.model.naming.ImplicitNamingStrategy; import org.hibernate.boot.model.naming.ImplicitNamingStrategy;
import org.hibernate.boot.model.naming.ImplicitUniqueKeyNameSource;
import org.hibernate.boot.model.naming.PhysicalNamingStrategy; import org.hibernate.boot.model.naming.PhysicalNamingStrategy;
import org.hibernate.boot.model.relational.Database; import org.hibernate.boot.model.relational.Database;
import org.hibernate.boot.spi.MetadataBuildingContext; import org.hibernate.boot.spi.MetadataBuildingContext;
@ -28,9 +25,7 @@
import java.util.Locale; import java.util.Locale;
import java.util.StringTokenizer; import java.util.StringTokenizer;
import static java.util.Collections.emptyList;
import static org.hibernate.internal.util.StringHelper.isEmpty; import static org.hibernate.internal.util.StringHelper.isEmpty;
import static org.hibernate.internal.util.collections.CollectionHelper.arrayList;
/** /**
* Responsible for interpreting {@link jakarta.persistence.Index} and * Responsible for interpreting {@link jakarta.persistence.Index} and
@ -233,57 +228,4 @@ else if ( tmp.endsWith( " asc" ) ) {
} }
} }
} }
private class IndexOrUniqueKeyNameSource implements ImplicitIndexNameSource, ImplicitUniqueKeyNameSource {
private final MetadataBuildingContext buildingContext;
private final Table table;
private final String[] columnNames;
private final String originalKeyName;
public IndexOrUniqueKeyNameSource(MetadataBuildingContext buildingContext, Table table, String[] columnNames, String originalKeyName) {
this.buildingContext = buildingContext;
this.table = table;
this.columnNames = columnNames;
this.originalKeyName = originalKeyName;
}
@Override
public MetadataBuildingContext getBuildingContext() {
return buildingContext;
}
@Override
public Identifier getTableName() {
return table.getNameIdentifier();
}
private List<Identifier> columnNameIdentifiers;
@Override
public List<Identifier> getColumnNames() {
// be lazy about building these
if ( columnNameIdentifiers == null ) {
columnNameIdentifiers = toIdentifiers( columnNames );
}
return columnNameIdentifiers;
}
@Override
public Identifier getUserProvidedIdentifier() {
return originalKeyName != null ? Identifier.toIdentifier( originalKeyName ) : null;
}
}
private List<Identifier> toIdentifiers(String[] names) {
if ( names == null ) {
return emptyList();
}
final List<Identifier> columnNames = arrayList( names.length );
for ( String name : names ) {
columnNames.add( getDatabase().toIdentifier( name ) );
}
return columnNames;
}
} }

View File

@ -0,0 +1,72 @@
/*
* 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.boot.model.internal;
import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.boot.model.naming.ImplicitIndexNameSource;
import org.hibernate.boot.model.naming.ImplicitUniqueKeyNameSource;
import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.mapping.Table;
import java.util.List;
import static java.util.Collections.emptyList;
import static org.hibernate.boot.model.naming.Identifier.toIdentifier;
import static org.hibernate.internal.util.collections.CollectionHelper.arrayList;
class IndexOrUniqueKeyNameSource implements ImplicitIndexNameSource, ImplicitUniqueKeyNameSource {
private final MetadataBuildingContext buildingContext;
private final Table table;
private final String[] columnNames;
private final String originalKeyName;
public IndexOrUniqueKeyNameSource(
MetadataBuildingContext buildingContext, Table table, String[] columnNames, String originalKeyName) {
this.buildingContext = buildingContext;
this.table = table;
this.columnNames = columnNames;
this.originalKeyName = originalKeyName;
}
@Override
public MetadataBuildingContext getBuildingContext() {
return buildingContext;
}
@Override
public Identifier getTableName() {
return table.getNameIdentifier();
}
private List<Identifier> columnNameIdentifiers;
@Override
public List<Identifier> getColumnNames() {
// be lazy about building these
if ( columnNameIdentifiers == null ) {
columnNameIdentifiers = toIdentifiers( columnNames );
}
return columnNameIdentifiers;
}
@Override
public Identifier getUserProvidedIdentifier() {
return originalKeyName != null ? toIdentifier( originalKeyName ) : null;
}
private List<Identifier> toIdentifiers(String[] names) {
if ( names == null ) {
return emptyList();
}
final List<Identifier> columnNames = arrayList( names.length );
for ( String name : names ) {
columnNames.add( buildingContext.getMetadataCollector().getDatabase().toIdentifier( name ) );
}
return columnNames;
}
}

View File

@ -568,7 +568,7 @@ else if ( firstColumn.isImplicit() ) {
} }
value.createForeignKey( referencedEntity, joinColumns ); value.createForeignKey( referencedEntity, joinColumns );
if ( unique ) { if ( unique ) {
value.createUniqueKey(); value.createUniqueKey( buildingContext );
} }
} }

View File

@ -11,7 +11,10 @@
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.boot.model.source.spi.AttributePath; import org.hibernate.boot.model.source.spi.AttributePath;
import org.hibernate.boot.spi.MetadataBuildingContext; import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.internal.util.StringHelper;
import static org.hibernate.boot.model.naming.ImplicitJoinColumnNameSource.Nature.ELEMENT_COLLECTION;
import static org.hibernate.internal.util.StringHelper.isNotEmpty;
import static org.hibernate.internal.util.StringHelper.unqualify;
/** /**
* Implementation of the {@link ImplicitNamingStrategy} contract, generally * Implementation of the {@link ImplicitNamingStrategy} contract, generally
@ -47,12 +50,12 @@ public Identifier determinePrimaryTableName(ImplicitEntityNameSource source) {
protected String transformEntityName(EntityNaming entityNaming) { protected String transformEntityName(EntityNaming entityNaming) {
// prefer the JPA entity name, if specified... // prefer the JPA entity name, if specified...
if ( StringHelper.isNotEmpty( entityNaming.getJpaEntityName() ) ) { if ( isNotEmpty( entityNaming.getJpaEntityName() ) ) {
return entityNaming.getJpaEntityName(); return entityNaming.getJpaEntityName();
} }
else { else {
// otherwise, use the Hibernate entity name // otherwise, use the Hibernate entity name
return StringHelper.unqualify( entityNaming.getEntityName() ); return unqualify( entityNaming.getEntityName() );
} }
} }
@ -67,7 +70,6 @@ public Identifier determineJoinTableName(ImplicitJoinTableNameSource source) {
final String name = source.getOwningPhysicalTableName() final String name = source.getOwningPhysicalTableName()
+ '_' + '_'
+ source.getNonOwningPhysicalTableName(); + source.getNonOwningPhysicalTableName();
return toIdentifier( name, source.getBuildingContext() ); return toIdentifier( name, source.getBuildingContext() );
} }
@ -80,12 +82,9 @@ public Identifier determineCollectionTableName(ImplicitCollectionTableNameSource
// aka: // aka:
// if owning entity has a JPA entity name: {OWNER JPA ENTITY NAME}_{COLLECTION ATTRIBUTE NAME} // if owning entity has a JPA entity name: {OWNER JPA ENTITY NAME}_{COLLECTION ATTRIBUTE NAME}
// otherwise: {OWNER ENTITY NAME}_{COLLECTION ATTRIBUTE NAME} // otherwise: {OWNER ENTITY NAME}_{COLLECTION ATTRIBUTE NAME}
final String entityName = transformEntityName( source.getOwningEntityNaming() ); final String name = transformEntityName( source.getOwningEntityNaming() )
final String name = entityName
+ '_' + '_'
+ transformAttributePath( source.getOwningAttributePath() ); + transformAttributePath( source.getOwningAttributePath() );
return toIdentifier( name, source.getBuildingContext() ); return toIdentifier( name, source.getBuildingContext() );
} }
@ -141,16 +140,15 @@ public Identifier determineJoinColumnName(ImplicitJoinColumnNameSource source) {
final String name; final String name;
if ( source.getNature() == ImplicitJoinColumnNameSource.Nature.ELEMENT_COLLECTION String referencedColumnName = source.getReferencedColumnName().getText();
if ( source.getNature() == ELEMENT_COLLECTION
|| source.getAttributePath() == null ) { || source.getAttributePath() == null ) {
name = transformEntityName( source.getEntityNaming() ) name = transformEntityName( source.getEntityNaming() )
+ '_' + '_' + referencedColumnName;
+ source.getReferencedColumnName().getText();
} }
else { else {
name = transformAttributePath( source.getAttributePath() ) name = transformAttributePath( source.getAttributePath() )
+ '_' + '_' + referencedColumnName;
+ source.getReferencedColumnName().getText();
} }
return toIdentifier( name, source.getBuildingContext() ); return toIdentifier( name, source.getBuildingContext() );
@ -165,17 +163,21 @@ public Identifier determinePrimaryKeyJoinColumnName(ImplicitPrimaryKeyJoinColumn
@Override @Override
public Identifier determineAnyDiscriminatorColumnName(ImplicitAnyDiscriminatorColumnNameSource source) { public Identifier determineAnyDiscriminatorColumnName(ImplicitAnyDiscriminatorColumnNameSource source) {
final MetadataBuildingContext buildingContext = source.getBuildingContext();
return toIdentifier( return toIdentifier(
transformAttributePath( source.getAttributePath() ) + "_" + source.getBuildingContext().getMappingDefaults().getImplicitDiscriminatorColumnName(), transformAttributePath( source.getAttributePath() )
source.getBuildingContext() + "_" + buildingContext.getMappingDefaults().getImplicitDiscriminatorColumnName(),
buildingContext
); );
} }
@Override @Override
public Identifier determineAnyKeyColumnName(ImplicitAnyKeyColumnNameSource source) { public Identifier determineAnyKeyColumnName(ImplicitAnyKeyColumnNameSource source) {
final MetadataBuildingContext buildingContext = source.getBuildingContext();
return toIdentifier( return toIdentifier(
transformAttributePath( source.getAttributePath() ) + "_" + source.getBuildingContext().getMappingDefaults().getImplicitIdColumnName(), transformAttributePath( source.getAttributePath() )
source.getBuildingContext() + "_" + buildingContext.getMappingDefaults().getImplicitIdColumnName(),
buildingContext
); );
} }
@ -198,41 +200,35 @@ public Identifier determineListIndexColumnName(ImplicitIndexColumnNameSource sou
@Override @Override
public Identifier determineForeignKeyName(ImplicitForeignKeyNameSource source) { public Identifier determineForeignKeyName(ImplicitForeignKeyNameSource source) {
Identifier userProvidedIdentifier = source.getUserProvidedIdentifier(); final Identifier userProvidedIdentifier = source.getUserProvidedIdentifier();
final MetadataBuildingContext buildingContext = source.getBuildingContext();
return userProvidedIdentifier != null ? userProvidedIdentifier : toIdentifier( return userProvidedIdentifier != null ? userProvidedIdentifier : toIdentifier(
NamingHelper.withCharset( source.getBuildingContext().getBuildingOptions().getSchemaCharset() ).generateHashedFkName( NamingHelper.withCharset( buildingContext.getBuildingOptions().getSchemaCharset() )
"FK", .generateHashedFkName( "FK", source.getTableName(),
source.getTableName(), source.getReferencedTableName(), source.getColumnNames() ),
source.getReferencedTableName(), buildingContext
source.getColumnNames()
),
source.getBuildingContext()
); );
} }
@Override @Override
public Identifier determineUniqueKeyName(ImplicitUniqueKeyNameSource source) { public Identifier determineUniqueKeyName(ImplicitUniqueKeyNameSource source) {
Identifier userProvidedIdentifier = source.getUserProvidedIdentifier(); final Identifier userProvidedIdentifier = source.getUserProvidedIdentifier();
final MetadataBuildingContext buildingContext = source.getBuildingContext();
return userProvidedIdentifier != null ? userProvidedIdentifier : toIdentifier( return userProvidedIdentifier != null ? userProvidedIdentifier : toIdentifier(
NamingHelper.withCharset( source.getBuildingContext().getBuildingOptions().getSchemaCharset() ).generateHashedConstraintName( NamingHelper.withCharset( buildingContext.getBuildingOptions().getSchemaCharset() )
"UK", .generateHashedConstraintName( "UK", source.getTableName(), source.getColumnNames() ),
source.getTableName(), buildingContext
source.getColumnNames()
),
source.getBuildingContext()
); );
} }
@Override @Override
public Identifier determineIndexName(ImplicitIndexNameSource source) { public Identifier determineIndexName(ImplicitIndexNameSource source) {
Identifier userProvidedIdentifier = source.getUserProvidedIdentifier(); final Identifier userProvidedIdentifier = source.getUserProvidedIdentifier();
final MetadataBuildingContext buildingContext = source.getBuildingContext();
return userProvidedIdentifier != null ? userProvidedIdentifier : toIdentifier( return userProvidedIdentifier != null ? userProvidedIdentifier : toIdentifier(
NamingHelper.withCharset( source.getBuildingContext().getBuildingOptions().getSchemaCharset() ).generateHashedConstraintName( NamingHelper.withCharset( buildingContext.getBuildingOptions().getSchemaCharset() )
"IDX", .generateHashedConstraintName( "IDX", source.getTableName(), source.getColumnNames() ),
source.getTableName(), buildingContext
source.getColumnNames()
),
source.getBuildingContext()
); );
} }

View File

@ -16,6 +16,8 @@
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import static java.util.Comparator.comparing;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
*/ */
@ -48,19 +50,13 @@ public String generateHashedFkName(
Identifier tableName, Identifier tableName,
Identifier referencedTableName, Identifier referencedTableName,
List<Identifier> columnNames) { List<Identifier> columnNames) {
final Identifier[] columnNamesArray;
if ( columnNames == null || columnNames.isEmpty() ) {
columnNamesArray = new Identifier[0];
}
else {
columnNamesArray = columnNames.toArray( new Identifier[ columnNames.size() ] );
}
return generateHashedFkName( return generateHashedFkName(
prefix, prefix,
tableName, tableName,
referencedTableName, referencedTableName,
columnNamesArray columnNames == null || columnNames.isEmpty()
? new Identifier[0]
: columnNames.toArray( new Identifier[0] )
); );
} }
@ -118,15 +114,7 @@ public String generateHashedConstraintName(String prefix, Identifier tableName,
// Clone the list, as sometimes a set of order-dependent Column // Clone the list, as sometimes a set of order-dependent Column
// bindings are given. // bindings are given.
Identifier[] alphabeticalColumns = columnNames.clone(); Identifier[] alphabeticalColumns = columnNames.clone();
Arrays.sort( Arrays.sort( alphabeticalColumns, comparing(Identifier::getCanonicalName) );
alphabeticalColumns,
new Comparator<Identifier>() {
@Override
public int compare(Identifier o1, Identifier o2) {
return o1.getCanonicalName().compareTo( o2.getCanonicalName() );
}
}
);
for ( Identifier columnName : alphabeticalColumns ) { for ( Identifier columnName : alphabeticalColumns ) {
sb.append( "column`" ).append( columnName ).append( "`" ); sb.append( "column`" ).append( columnName ).append( "`" );
} }

View File

@ -160,9 +160,12 @@
import org.hibernate.usertype.ParameterizedType; import org.hibernate.usertype.ParameterizedType;
import org.hibernate.usertype.UserType; import org.hibernate.usertype.UserType;
import static org.hibernate.boot.model.naming.Identifier.toIdentifier;
import static org.hibernate.boot.model.source.internal.hbm.Helper.reflectedPropertyClass;
import static org.hibernate.cfg.AvailableSettings.USE_ENTITY_WHERE_CLAUSE_FOR_COLLECTIONS; import static org.hibernate.cfg.AvailableSettings.USE_ENTITY_WHERE_CLAUSE_FOR_COLLECTIONS;
import static org.hibernate.internal.log.DeprecationLogger.DEPRECATION_LOGGER; import static org.hibernate.internal.log.DeprecationLogger.DEPRECATION_LOGGER;
import static org.hibernate.internal.util.StringHelper.getNonEmptyOrConjunctionIfBothNonEmpty; import static org.hibernate.internal.util.StringHelper.getNonEmptyOrConjunctionIfBothNonEmpty;
import static org.hibernate.internal.util.StringHelper.isNotEmpty;
import static org.hibernate.internal.util.collections.CollectionHelper.isEmpty; import static org.hibernate.internal.util.collections.CollectionHelper.isEmpty;
import static org.hibernate.mapping.SimpleValue.DEFAULT_ID_GEN_STRATEGY; import static org.hibernate.mapping.SimpleValue.DEFAULT_ID_GEN_STRATEGY;
@ -406,7 +409,7 @@ private void bindBasicEntityValues(
); );
// NOTE : entitySource#isLazy already accounts for MappingDefaults#areEntitiesImplicitlyLazy // NOTE : entitySource#isLazy already accounts for MappingDefaults#areEntitiesImplicitlyLazy
if ( StringHelper.isNotEmpty( entitySource.getProxy() ) ) { if ( isNotEmpty( entitySource.getProxy() ) ) {
final String qualifiedProxyName = sourceDocument.qualifyClassName( entitySource.getProxy() ); final String qualifiedProxyName = sourceDocument.qualifyClassName( entitySource.getProxy() );
entityDescriptor.setProxyInterfaceName( qualifiedProxyName ); entityDescriptor.setProxyInterfaceName( qualifiedProxyName );
entityDescriptor.setLazy( true ); entityDescriptor.setLazy( true );
@ -439,7 +442,7 @@ else if ( entitySource.isLazy() ) {
entityDescriptor.setBatchSize( entitySource.getBatchSize() ); entityDescriptor.setBatchSize( entitySource.getBatchSize() );
entityDescriptor.setSelectBeforeUpdate( entitySource.isSelectBeforeUpdate() ); entityDescriptor.setSelectBeforeUpdate( entitySource.isSelectBeforeUpdate() );
if ( StringHelper.isNotEmpty( entitySource.getCustomPersisterClassName() ) ) { if ( isNotEmpty( entitySource.getCustomPersisterClassName() ) ) {
try { try {
entityDescriptor.setEntityPersisterClass( entityDescriptor.setEntityPersisterClass(
sourceDocument.getBootstrapContext() sourceDocument.getBootstrapContext()
@ -623,8 +626,8 @@ private void bindJoinedSubclassEntity(
int count = 0; int count = 0;
@Override @Override
public Identifier determineImplicitName(LocalMetadataBuildingContext context) { public Identifier determineImplicitName(LocalMetadataBuildingContext context) {
final Column column = primaryTable.getPrimaryKey().getColumn( count++ ); return primaryTable.getPrimaryKey().getColumn( count++ )
return database.toIdentifier( column.getQuotedName() ); .getNameIdentifier( metadataBuildingContext );
} }
} }
); );
@ -799,7 +802,7 @@ private void makeIdentifier(
identifierValue.getTable().setIdentifierValue( identifierValue ); identifierValue.getTable().setIdentifierValue( identifierValue );
if ( StringHelper.isNotEmpty( unsavedValue ) ) { if ( isNotEmpty( unsavedValue ) ) {
identifierValue.setNullValue( unsavedValue ); identifierValue.setNullValue( unsavedValue );
} }
else if ( DEFAULT_ID_GEN_STRATEGY.equals( identifierValue.getIdentifierGeneratorStrategy() ) ) { else if ( DEFAULT_ID_GEN_STRATEGY.equals( identifierValue.getIdentifierGeneratorStrategy() ) ) {
@ -1696,7 +1699,7 @@ private void bindSecondaryTable(
inLineViewSource.getSelectStatement(), inLineViewSource.getSelectStatement(),
false false
); );
logicalTableName = Identifier.toIdentifier( inLineViewSource.getLogicalName() ); logicalTableName = toIdentifier( inLineViewSource.getLogicalName() );
} }
secondaryTableJoin.setTable( secondaryTable ); secondaryTableJoin.setTable( secondaryTable );
@ -1738,8 +1741,8 @@ private void bindSecondaryTable(
int count = 0; int count = 0;
@Override @Override
public Identifier determineImplicitName(LocalMetadataBuildingContext context) { public Identifier determineImplicitName(LocalMetadataBuildingContext context) {
final Column correspondingColumn = entityTableXref.getPrimaryTable().getPrimaryKey().getColumn( count++ ); return entityTableXref.getPrimaryTable().getPrimaryKey().getColumn( count++ )
return database.toIdentifier( correspondingColumn.getQuotedName() ); .getNameIdentifier( metadataBuildingContext );
} }
} }
); );
@ -2062,7 +2065,7 @@ public void bindOneToOne(
oneToOneBinding.setUnwrapProxy( oneToOneSource.getFetchCharacteristics().isUnwrapProxies() ); oneToOneBinding.setUnwrapProxy( oneToOneSource.getFetchCharacteristics().isUnwrapProxies() );
if ( StringHelper.isNotEmpty( oneToOneSource.getReferencedEntityAttributeName() ) ) { if ( isNotEmpty( oneToOneSource.getReferencedEntityAttributeName() ) ) {
oneToOneBinding.setReferencedPropertyName( oneToOneSource.getReferencedEntityAttributeName() ); oneToOneBinding.setReferencedPropertyName( oneToOneSource.getReferencedEntityAttributeName() );
oneToOneBinding.setReferenceToPrimaryKey( false ); oneToOneBinding.setReferenceToPrimaryKey( false );
} }
@ -2077,7 +2080,7 @@ public void bindOneToOne(
DEPRECATION_LOGGER.logDeprecationOfEmbedXmlSupport(); DEPRECATION_LOGGER.logDeprecationOfEmbedXmlSupport();
} }
if ( StringHelper.isNotEmpty( oneToOneSource.getExplicitForeignKeyName() ) ) { if ( isNotEmpty( oneToOneSource.getExplicitForeignKeyName() ) ) {
oneToOneBinding.setForeignKeyName( oneToOneSource.getExplicitForeignKeyName() ); oneToOneBinding.setForeignKeyName( oneToOneSource.getExplicitForeignKeyName() );
} }
@ -2096,7 +2099,7 @@ private Property createManyToOneAttribute(
referencedEntityName = manyToOneSource.getReferencedEntityName(); referencedEntityName = manyToOneSource.getReferencedEntityName();
} }
else { else {
Class<?> reflectedPropertyClass = Helper.reflectedPropertyClass( sourceDocument, containingClassName, attributeName ); Class<?> reflectedPropertyClass = reflectedPropertyClass( sourceDocument, containingClassName, attributeName );
if ( reflectedPropertyClass != null ) { if ( reflectedPropertyClass != null ) {
referencedEntityName = reflectedPropertyClass.getName(); referencedEntityName = reflectedPropertyClass.getName();
} }
@ -2137,7 +2140,7 @@ private Property createManyToOneAttribute(
prop prop
); );
if ( StringHelper.isNotEmpty( manyToOneSource.getCascadeStyleName() ) ) { if ( isNotEmpty( manyToOneSource.getCascadeStyleName() ) ) {
// todo : would be better to delay this the end of binding (second pass, etc) // todo : would be better to delay this the end of binding (second pass, etc)
// in order to properly allow for a singular unique column for a many-to-one to // in order to properly allow for a singular unique column for a many-to-one to
// also trigger a "logical one-to-one". As-is, this can occasionally lead to // also trigger a "logical one-to-one". As-is, this can occasionally lead to
@ -2174,7 +2177,7 @@ private void bindManyToOneAttribute(
// NOTE : no type information to bind // NOTE : no type information to bind
manyToOneBinding.setReferencedEntityName( referencedEntityName ); manyToOneBinding.setReferencedEntityName( referencedEntityName );
if ( StringHelper.isNotEmpty( manyToOneSource.getReferencedEntityAttributeName() ) ) { if ( isNotEmpty( manyToOneSource.getReferencedEntityAttributeName() ) ) {
manyToOneBinding.setReferencedPropertyName( manyToOneSource.getReferencedEntityAttributeName() ); manyToOneBinding.setReferencedPropertyName( manyToOneSource.getReferencedEntityAttributeName() );
manyToOneBinding.setReferenceToPrimaryKey( false ); manyToOneBinding.setReferenceToPrimaryKey( false );
} }
@ -2196,7 +2199,7 @@ private void bindManyToOneAttribute(
manyToOneBinding.setIgnoreNotFound( manyToOneSource.isIgnoreNotFound() ); manyToOneBinding.setIgnoreNotFound( manyToOneSource.isIgnoreNotFound() );
if ( StringHelper.isNotEmpty( manyToOneSource.getExplicitForeignKeyName() ) ) { if ( isNotEmpty( manyToOneSource.getExplicitForeignKeyName() ) ) {
manyToOneBinding.setForeignKeyName( manyToOneSource.getExplicitForeignKeyName() ); manyToOneBinding.setForeignKeyName( manyToOneSource.getExplicitForeignKeyName() );
} }
@ -2465,7 +2468,7 @@ private void bindProperty(
property.setName( propertySource.getName() ); property.setName( propertySource.getName() );
property.setPropertyAccessorName( property.setPropertyAccessorName(
StringHelper.isNotEmpty( propertySource.getPropertyAccessorName() ) isNotEmpty( propertySource.getPropertyAccessorName() )
? propertySource.getPropertyAccessorName() ? propertySource.getPropertyAccessorName()
: mappingDocument.getMappingDefaults().getImplicitPropertyAccessorName() : mappingDocument.getMappingDefaults().getImplicitPropertyAccessorName()
); );
@ -2474,7 +2477,7 @@ private void bindProperty(
final CascadeStyleSource cascadeStyleSource = (CascadeStyleSource) propertySource; final CascadeStyleSource cascadeStyleSource = (CascadeStyleSource) propertySource;
property.setCascade( property.setCascade(
StringHelper.isNotEmpty( cascadeStyleSource.getCascadeStyleName() ) isNotEmpty( cascadeStyleSource.getCascadeStyleName() )
? cascadeStyleSource.getCascadeStyleName() ? cascadeStyleSource.getCascadeStyleName()
: mappingDocument.getMappingDefaults().getImplicitCascadeStyleName() : mappingDocument.getMappingDefaults().getImplicitCascadeStyleName()
); );
@ -2613,7 +2616,7 @@ else if ( isVirtual ) {
} }
else { else {
log.debugf( "Binding component [%s]", role ); log.debugf( "Binding component [%s]", role );
if ( StringHelper.isNotEmpty( explicitComponentClassName ) ) { if ( isNotEmpty( explicitComponentClassName ) ) {
try { try {
final Class<Object> componentClass = sourceDocument.getBootstrapContext() final Class<Object> componentClass = sourceDocument.getBootstrapContext()
.getClassLoaderAccess() .getClassLoaderAccess()
@ -2643,12 +2646,8 @@ else if ( isVirtual ) {
else if ( componentBinding.getOwner().hasPojoRepresentation() ) { else if ( componentBinding.getOwner().hasPojoRepresentation() ) {
log.tracef( "Attempting to determine component class by reflection %s", role ); log.tracef( "Attempting to determine component class by reflection %s", role );
final Class<?> reflectedComponentClass; final Class<?> reflectedComponentClass;
if ( StringHelper.isNotEmpty( containingClassName ) && StringHelper.isNotEmpty( propertyName ) ) { if ( isNotEmpty( containingClassName ) && isNotEmpty( propertyName ) ) {
reflectedComponentClass = Helper.reflectedPropertyClass( reflectedComponentClass = reflectedPropertyClass( sourceDocument, containingClassName, propertyName );
sourceDocument,
containingClassName,
propertyName
);
} }
else { else {
reflectedComponentClass = null; reflectedComponentClass = null;
@ -2671,11 +2670,7 @@ else if ( componentBinding.getOwner().hasPojoRepresentation() ) {
} }
// todo : anything else to pass along? // todo : anything else to pass along?
bindAllCompositeAttributes( bindAllCompositeAttributes( sourceDocument, embeddableSource, componentBinding );
sourceDocument,
embeddableSource,
componentBinding
);
if ( embeddableSource.getParentReferenceAttributeName() != null ) { if ( embeddableSource.getParentReferenceAttributeName() != null ) {
componentBinding.setParentProperty( embeddableSource.getParentReferenceAttributeName() ); componentBinding.setParentProperty( embeddableSource.getParentReferenceAttributeName() );
@ -2689,7 +2684,7 @@ else if ( componentBinding.getOwner().hasPojoRepresentation() ) {
} }
} }
// todo : we may need to delay this // todo : we may need to delay this
componentBinding.getOwner().getTable().createUniqueKey( cols ); componentBinding.getOwner().getTable().createUniqueKey( cols, metadataBuildingContext );
} }
} }
@ -2847,7 +2842,7 @@ private Table bindEntityTableSpecification(
if ( isTable ) { if ( isTable ) {
final TableSource tableSource = (TableSource) tableSpecSource; final TableSource tableSource = (TableSource) tableSpecSource;
if ( StringHelper.isNotEmpty( tableSource.getExplicitTableName() ) ) { if ( isNotEmpty( tableSource.getExplicitTableName() ) ) {
logicalTableName = database.toIdentifier( tableSource.getExplicitTableName() ); logicalTableName = database.toIdentifier( tableSource.getExplicitTableName() );
} }
else { else {
@ -2939,7 +2934,7 @@ public MetadataBuildingContext getBuildingContext() {
if ( isTable ) { if ( isTable ) {
final TableSource tableSource = (TableSource) tableSpecSource; final TableSource tableSource = (TableSource) tableSpecSource;
table.setRowId( tableSource.getRowId() ); table.setRowId( tableSource.getRowId() );
if ( StringHelper.isNotEmpty( tableSource.getCheckConstraint() ) ) { if ( isNotEmpty( tableSource.getCheckConstraint() ) ) {
table.addCheckConstraint( tableSource.getCheckConstraint() ); table.addCheckConstraint( tableSource.getCheckConstraint() );
} }
} }
@ -2952,7 +2947,7 @@ public MetadataBuildingContext getBuildingContext() {
} }
private Identifier determineCatalogName(TableSpecificationSource tableSpecSource) { private Identifier determineCatalogName(TableSpecificationSource tableSpecSource) {
if ( StringHelper.isNotEmpty( tableSpecSource.getExplicitCatalogName() ) ) { if ( isNotEmpty( tableSpecSource.getExplicitCatalogName() ) ) {
return database.toIdentifier( tableSpecSource.getExplicitCatalogName() ); return database.toIdentifier( tableSpecSource.getExplicitCatalogName() );
} }
else { else {
@ -2961,7 +2956,7 @@ private Identifier determineCatalogName(TableSpecificationSource tableSpecSource
} }
private Identifier determineSchemaName(TableSpecificationSource tableSpecSource) { private Identifier determineSchemaName(TableSpecificationSource tableSpecSource) {
if ( StringHelper.isNotEmpty( tableSpecSource.getExplicitSchemaName() ) ) { if ( isNotEmpty( tableSpecSource.getExplicitSchemaName() ) ) {
return database.toIdentifier( tableSpecSource.getExplicitSchemaName() ); return database.toIdentifier( tableSpecSource.getExplicitSchemaName() );
} }
else { else {
@ -3183,8 +3178,8 @@ private void bindCollectionTable() {
final TableSource tableSource = (TableSource) tableSpecSource; final TableSource tableSource = (TableSource) tableSpecSource;
Identifier logicalName; Identifier logicalName;
if ( StringHelper.isNotEmpty( tableSource.getExplicitTableName() ) ) { if ( isNotEmpty( tableSource.getExplicitTableName() ) ) {
logicalName = Identifier.toIdentifier( logicalName = toIdentifier(
tableSource.getExplicitTableName(), tableSource.getExplicitTableName(),
mappingDocument.getMappingDefaults().shouldImplicitlyQuoteIdentifiers() mappingDocument.getMappingDefaults().shouldImplicitlyQuoteIdentifiers()
); );
@ -3486,7 +3481,7 @@ else if ( getPluralAttributeSource().getElementSource() instanceof PluralAttribu
elementBinding.setForeignKeyName( elementSource.getExplicitForeignKeyName() ); elementBinding.setForeignKeyName( elementSource.getExplicitForeignKeyName() );
elementBinding.setReferencedEntityName( elementSource.getReferencedEntityName() ); elementBinding.setReferencedEntityName( elementSource.getReferencedEntityName() );
if ( StringHelper.isNotEmpty( elementSource.getReferencedEntityAttributeName() ) ) { if ( isNotEmpty( elementSource.getReferencedEntityAttributeName() ) ) {
elementBinding.setReferencedPropertyName( elementSource.getReferencedEntityAttributeName() ); elementBinding.setReferencedPropertyName( elementSource.getReferencedEntityAttributeName() );
elementBinding.setReferenceToPrimaryKey( false ); elementBinding.setReferenceToPrimaryKey( false );
} }
@ -4180,15 +4175,14 @@ public void process() {
if ( selectable instanceof Column ) { if ( selectable instanceof Column ) {
final Column column = (Column) selectable; final Column column = (Column) selectable;
uk.addColumn( column ); uk.addColumn( column );
columnNames.add( columnNames.add( column.getNameIdentifier( mappingDocument ) );
mappingDocument.getMetadataCollector().getDatabase().toIdentifier( column.getQuotedName() )
);
} }
} }
uk.addColumns( attributeBinding.getValue() ); uk.addColumns( attributeBinding.getValue() );
} }
final Identifier ukName = mappingDocument.getBuildingOptions().getImplicitNamingStrategy().determineUniqueKeyName( final Identifier ukName = mappingDocument.getBuildingOptions().getImplicitNamingStrategy()
.determineUniqueKeyName(
new ImplicitUniqueKeyNameSource() { new ImplicitUniqueKeyNameSource() {
@Override @Override
public Identifier getTableName() { public Identifier getTableName() {
@ -4207,7 +4201,8 @@ public MetadataBuildingContext getBuildingContext() {
@Override @Override
public Identifier getUserProvidedIdentifier() { public Identifier getUserProvidedIdentifier() {
return uk.getName() != null ? Identifier.toIdentifier( uk.getName() ) : null; final String name = uk.getName();
return name == null ? null : toIdentifier( name );
} }
} }
); );

View File

@ -155,6 +155,9 @@ public void bindColumn(
column.setNullable( interpretNullability( columnSource.isNullable(), areColumnsNullableByDefault ) ); column.setNullable( interpretNullability( columnSource.isNullable(), areColumnsNullableByDefault ) );
column.setUnique( columnSource.isUnique() ); column.setUnique( columnSource.isUnique() );
if ( columnSource.isUnique() && table != null ) {
table.createUniqueKey( column, simpleValue.getBuildingContext() );
}
String checkCondition = columnSource.getCheckCondition(); String checkCondition = columnSource.getCheckCondition();
if ( checkCondition != null ) { if ( checkCondition != null ) {

View File

@ -139,7 +139,7 @@ public void createForeignKey() {
} }
@Override @Override
public void createUniqueKey() { public void createUniqueKey(MetadataBuildingContext context) {
} }
@Override @Override

View File

@ -29,6 +29,7 @@ public AggregateColumn(Column column, Component component) {
setName( column.getQuotedName() ); setName( column.getQuotedName() );
setNullable( column.isNullable() ); setNullable( column.isNullable() );
setUnique( column.isUnique() ); setUnique( column.isUnique() );
setUniqueKeyName( column.getUniqueKeyName() );
setSqlType( column.getSqlType() ); setSqlType( column.getSqlType() );
setSqlTypeCode( column.getSqlTypeCode() ); setSqlTypeCode( column.getSqlTypeCode() );
uniqueInteger = column.uniqueInteger; //usually useless uniqueInteger = column.uniqueInteger; //usually useless

View File

@ -499,7 +499,7 @@ public void createForeignKey() {
} }
@Override @Override
public void createUniqueKey() { public void createUniqueKey(MetadataBuildingContext context) {
} }
public boolean isSimpleValue() { public boolean isSimpleValue() {

View File

@ -13,17 +13,19 @@
import java.util.Objects; import java.util.Objects;
import org.hibernate.AssertionFailure; import org.hibernate.AssertionFailure;
import org.hibernate.Internal;
import org.hibernate.MappingException; import org.hibernate.MappingException;
import org.hibernate.boot.Metadata; import org.hibernate.boot.Metadata;
import org.hibernate.boot.model.TruthValue; import org.hibernate.boot.model.TruthValue;
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.spi.MetadataBuildingContext;
import org.hibernate.dialect.Dialect; import org.hibernate.dialect.Dialect;
import org.hibernate.engine.jdbc.Size; import org.hibernate.engine.jdbc.Size;
import org.hibernate.engine.spi.Mapping; import org.hibernate.engine.spi.Mapping;
import org.hibernate.loader.internal.AliasConstantsHelper; import org.hibernate.loader.internal.AliasConstantsHelper;
import org.hibernate.metamodel.mapping.JdbcMapping; import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.query.sqm.function.SqmFunctionRegistry; import org.hibernate.query.sqm.function.SqmFunctionRegistry;
import org.hibernate.query.sqm.internal.TypecheckUtil;
import org.hibernate.sql.Template; import org.hibernate.sql.Template;
import org.hibernate.tool.schema.extract.spi.ColumnTypeInformation; import org.hibernate.tool.schema.extract.spi.ColumnTypeInformation;
import org.hibernate.type.BasicType; import org.hibernate.type.BasicType;
@ -61,6 +63,7 @@ public class Column implements Selectable, Serializable, Cloneable, ColumnTypeIn
private String name; private String name;
private boolean nullable = true; private boolean nullable = true;
private boolean unique; private boolean unique;
private String uniqueKeyName;
private String sqlTypeName; private String sqlTypeName;
private Integer sqlTypeCode; private Integer sqlTypeCode;
private Boolean sqlTypeLob; private Boolean sqlTypeLob;
@ -126,6 +129,12 @@ public void setName(String name) {
} }
} }
@Internal
public Identifier getNameIdentifier(MetadataBuildingContext buildingContext) {
return buildingContext.getMetadataCollector().getDatabase()
.toIdentifier( getQuotedName() );
}
public boolean isExplicit() { public boolean isExplicit() {
return explicit; return explicit;
} }
@ -566,6 +575,14 @@ public void setUnique(boolean unique) {
this.unique = unique; this.unique = unique;
} }
public String getUniqueKeyName() {
return uniqueKeyName;
}
public void setUniqueKeyName(String keyName) {
uniqueKeyName = keyName;
}
public boolean isQuoted() { public boolean isQuoted() {
return quoted; return quoted;
} }
@ -778,6 +795,7 @@ public Column clone() {
copy.quoted = quoted; copy.quoted = quoted;
copy.nullable = nullable; copy.nullable = nullable;
copy.unique = unique; copy.unique = unique;
copy.uniqueKeyName = uniqueKeyName;
copy.sqlTypeName = sqlTypeName; copy.sqlTypeName = sqlTypeName;
copy.sqlTypeCode = sqlTypeCode; copy.sqlTypeCode = sqlTypeCode;
copy.uniqueInteger = uniqueInteger; //usually useless copy.uniqueInteger = uniqueInteger; //usually useless
@ -792,5 +810,4 @@ public Column clone() {
copy.columnSize = columnSize; copy.columnSize = columnSize;
return copy; return copy;
} }
} }

View File

@ -47,7 +47,10 @@ public void setName(String name) {
* They're cached, keyed by name, in multiple locations. * They're cached, keyed by name, in multiple locations.
* *
* @return String The generated name * @return String The generated name
*
* @deprecated This method does not respect the {@link org.hibernate.boot.model.naming.ImplicitNamingStrategy}
*/ */
@Deprecated(since = "6.5", forRemoval = true)
public static String generateName(String prefix, Table table, Column... columns) { public static String generateName(String prefix, Table table, Column... columns) {
// Use a concatenation that guarantees uniqueness, even if identical names // Use a concatenation that guarantees uniqueness, even if identical names
// exist between all table and column identifiers. // exist between all table and column identifiers.
@ -69,7 +72,10 @@ public static String generateName(String prefix, Table table, Column... columns)
* Helper method for {@link #generateName(String, Table, Column...)}. * Helper method for {@link #generateName(String, Table, Column...)}.
* *
* @return String The generated name * @return String The generated name
*
* @deprecated This method does not respect the {@link org.hibernate.boot.model.naming.ImplicitNamingStrategy}
*/ */
@Deprecated(since = "6.5", forRemoval = true)
public static String generateName(String prefix, Table table, List<Column> columns) { public static String generateName(String prefix, Table table, List<Column> columns) {
// N.B. legacy APIs are involved: can't trust that the columns List is actually // N.B. legacy APIs are involved: can't trust that the columns List is actually
// containing Column instances - the generic type isn't consistently enforced. // containing Column instances - the generic type isn't consistently enforced.
@ -89,7 +95,10 @@ public static String generateName(String prefix, Table table, List<Column> colum
* *
* @param name The name to be hashed. * @param name The name to be hashed.
* @return String The hashed name. * @return String The hashed name.
*
* @deprecated Only used from deprecated methods
*/ */
@Deprecated(since = "6.5", forRemoval = true)
public static String hashedName(String name) { public static String hashedName(String name) {
try { try {
final MessageDigest md = MessageDigest.getInstance( "MD5" ); final MessageDigest md = MessageDigest.getInstance( "MD5" );
@ -147,6 +156,10 @@ public void setTable(Table table) {
this.table = table; this.table = table;
} }
/**
* @deprecated No longer used
*/
@Deprecated(forRemoval = true)
public boolean isGenerated(Dialect dialect) { public boolean isGenerated(Dialect dialect) {
return true; return true;
} }
@ -172,6 +185,8 @@ public String toString() {
/** /**
* @return String The prefix to use in generated constraint names. Examples: * @return String The prefix to use in generated constraint names. Examples:
* "UK_", "FK_", and "PK_". * "UK_", "FK_", and "PK_".
* @deprecated No longer used, should be removed
*/ */
@Deprecated(since="6.5", forRemoval = true)
public abstract String generatedConstraintNamePrefix(); public abstract String generatedConstraintNamePrefix();
} }

View File

@ -12,8 +12,10 @@
import java.util.List; import java.util.List;
import org.hibernate.Internal; import org.hibernate.Internal;
import org.hibernate.boot.internal.ForeignKeyNameSource;
import org.hibernate.boot.model.naming.Identifier; import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.boot.model.relational.Namespace; import org.hibernate.boot.model.relational.Namespace;
import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.internal.util.collections.JoinedList; import org.hibernate.internal.util.collections.JoinedList;
/** /**
@ -59,15 +61,20 @@ public DenormalizedTable(
} }
@Override @Override
public void createForeignKeys() { public void createForeignKeys(MetadataBuildingContext context) {
includedTable.createForeignKeys(); includedTable.createForeignKeys( context );
for ( ForeignKey foreignKey : includedTable.getForeignKeys().values() ) { for ( ForeignKey foreignKey : includedTable.getForeignKeys().values() ) {
final PersistentClass referencedClass =
foreignKey.resolveReferencedClass( context.getMetadataCollector() );
// the ForeignKeys created in the first pass did not have their referenced table initialized
if ( foreignKey.getReferencedTable() == null ) {
foreignKey.setReferencedTable( referencedClass.getTable() );
}
createForeignKey( createForeignKey(
Constraint.generateName( context.getBuildingOptions()
foreignKey.generatedConstraintNamePrefix(), .getImplicitNamingStrategy()
this, .determineForeignKeyName( new ForeignKeyNameSource( foreignKey, this, context ) )
foreignKey.getColumns() .render( context.getMetadataCollector().getDatabase().getDialect() ),
),
foreignKey.getColumns(), foreignKey.getColumns(),
foreignKey.getReferencedEntityName(), foreignKey.getReferencedEntityName(),
foreignKey.getKeyDefinition(), foreignKey.getKeyDefinition(),
@ -105,7 +112,7 @@ public PrimaryKey getPrimaryKey() {
return includedTable.getPrimaryKey(); return includedTable.getPrimaryKey();
} }
@Override @Deprecated @Override @Deprecated(forRemoval = true)
public Iterator<UniqueKey> getUniqueKeyIterator() { public Iterator<UniqueKey> getUniqueKeyIterator() {
if ( !includedTable.isPhysicalTable() ) { if ( !includedTable.isPhysicalTable() ) {
for ( UniqueKey uniqueKey : includedTable.getUniqueKeys().values() ) { for ( UniqueKey uniqueKey : includedTable.getUniqueKeys().values() ) {

View File

@ -10,8 +10,10 @@
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import org.hibernate.Internal;
import org.hibernate.MappingException; import org.hibernate.MappingException;
import org.hibernate.annotations.OnDeleteAction; import org.hibernate.annotations.OnDeleteAction;
import org.hibernate.boot.Metadata;
import org.hibernate.boot.model.relational.SqlStringGenerationContext; import org.hibernate.boot.model.relational.SqlStringGenerationContext;
import org.hibernate.dialect.Dialect; import org.hibernate.dialect.Dialect;
@ -232,7 +234,25 @@ public String toString() {
} }
@Deprecated(forRemoval = true)
public String generatedConstraintNamePrefix() { public String generatedConstraintNamePrefix() {
return "FK_"; return "FK_";
} }
@Internal
public PersistentClass resolveReferencedClass(Metadata metadata) {
final String referencedEntityName = getReferencedEntityName();
if ( referencedEntityName == null ) {
throw new MappingException( "An association from the table '" + getTable().getName() +
"' does not specify the referenced entity" );
}
final PersistentClass referencedClass = metadata.getEntityBinding( referencedEntityName );
if ( referencedClass == null ) {
throw new MappingException( "An association from the table '" + getTable().getName() +
"' refers to an unmapped class '" + referencedEntityName + "'" );
}
return referencedClass;
}
} }

View File

@ -60,9 +60,9 @@ public Type getType() throws MappingException {
} }
@Override @Override
public void createUniqueKey() { public void createUniqueKey(MetadataBuildingContext context) {
if ( !hasFormula() ) { if ( !hasFormula() ) {
getTable().createUniqueKey( getConstraintColumns() ); getTable().createUniqueKey( getConstraintColumns(), context );
} }
} }

View File

@ -6,7 +6,6 @@
*/ */
package org.hibernate.mapping; package org.hibernate.mapping;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
@ -91,7 +90,7 @@ public void createForeignKey() {
} }
@Override @Override
public void createUniqueKey() { public void createUniqueKey(MetadataBuildingContext context) {
} }
@Override @Override

View File

@ -94,9 +94,9 @@ public Type getType() throws MappingException {
} }
@Override @Override
public void createUniqueKey() { public void createUniqueKey(MetadataBuildingContext context) {
if ( !hasFormula() && getColumnSpan()>0 ) { if ( !hasFormula() && getColumnSpan()>0 ) {
getTable().createUniqueKey( getConstraintColumns() ); getTable().createUniqueKey( getConstraintColumns(), context );
} }
} }

View File

@ -101,6 +101,7 @@ public String sqlConstraintString(SqlStringGenerationContext context, String con
return buf.append(')').toString(); return buf.append(')').toString();
} }
@Deprecated(forRemoval = true)
public String generatedConstraintNamePrefix() { public String generatedConstraintNamePrefix() {
return "PK_"; return "PK_";
} }

View File

@ -368,11 +368,11 @@ public ForeignKey createForeignKeyOfEntity(String entityName) {
} }
@Override @Override
public void createUniqueKey() { public void createUniqueKey(MetadataBuildingContext context) {
if ( hasFormula() ) { if ( hasFormula() ) {
throw new MappingException( "unique key constraint involves formulas" ); throw new MappingException( "unique key constraint involves formulas" );
} }
getTable().createUniqueKey( getConstraintColumns() ); getTable().createUniqueKey( getConstraintColumns(), context );
} }
/** /**

View File

@ -23,12 +23,14 @@
import org.hibernate.Remove; import org.hibernate.Remove;
import org.hibernate.boot.Metadata; import org.hibernate.boot.Metadata;
import org.hibernate.boot.model.naming.Identifier; import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.boot.model.naming.ImplicitUniqueKeyNameSource;
import org.hibernate.boot.model.relational.ContributableDatabaseObject; import org.hibernate.boot.model.relational.ContributableDatabaseObject;
import org.hibernate.boot.model.relational.InitCommand; import org.hibernate.boot.model.relational.InitCommand;
import org.hibernate.boot.model.relational.Namespace; import org.hibernate.boot.model.relational.Namespace;
import org.hibernate.boot.model.relational.QualifiedTableName; import org.hibernate.boot.model.relational.QualifiedTableName;
import org.hibernate.boot.model.relational.SqlStringGenerationContext; import org.hibernate.boot.model.relational.SqlStringGenerationContext;
import org.hibernate.boot.spi.InFlightMetadataCollector; import org.hibernate.boot.spi.InFlightMetadataCollector;
import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.dialect.Dialect; import org.hibernate.dialect.Dialect;
import org.hibernate.tool.schema.extract.spi.TableInformation; import org.hibernate.tool.schema.extract.spi.TableInformation;
@ -36,9 +38,11 @@
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
import static java.util.Collections.emptyList; import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
import static java.util.Collections.unmodifiableList; import static java.util.Collections.unmodifiableList;
import static java.util.Collections.unmodifiableMap; import static java.util.Collections.unmodifiableMap;
import static java.util.stream.Collectors.toList; import static java.util.stream.Collectors.toList;
import static org.hibernate.boot.model.naming.Identifier.toIdentifier;
/** /**
* A mapping model object representing a relational database {@linkplain jakarta.persistence.Table table}. * A mapping model object representing a relational database {@linkplain jakarta.persistence.Table table}.
@ -151,7 +155,7 @@ public static String qualify(String catalog, String schema, String table) {
} }
public void setName(String name) { public void setName(String name) {
this.name = Identifier.toIdentifier( name ); this.name = toIdentifier( name );
} }
public String getName() { public String getName() {
@ -193,7 +197,7 @@ public void setQuoted(boolean quoted) {
} }
public void setSchema(String schema) { public void setSchema(String schema) {
this.schema = Identifier.toIdentifier( schema ); this.schema = toIdentifier( schema );
} }
public String getSchema() { public String getSchema() {
@ -213,7 +217,7 @@ public boolean isSchemaQuoted() {
} }
public void setCatalog(String catalog) { public void setCatalog(String catalog) {
this.catalog = Identifier.toIdentifier( catalog ); this.catalog = toIdentifier( catalog );
} }
public String getCatalog() { public String getCatalog() {
@ -321,7 +325,10 @@ public Map<String, Index> getIndexes() {
return unmodifiableMap( indexes ); return unmodifiableMap( indexes );
} }
@Deprecated(since = "6.0") /**
* @deprecated No longer used, should be removed
*/
@Deprecated(since = "6.0", forRemoval = true)
public Iterator<ForeignKey> getForeignKeyIterator() { public Iterator<ForeignKey> getForeignKeyIterator() {
return getForeignKeys().values().iterator(); return getForeignKeys().values().iterator();
} }
@ -330,7 +337,10 @@ public Map<ForeignKeyKey, ForeignKey> getForeignKeys() {
return unmodifiableMap( foreignKeys ); return unmodifiableMap( foreignKeys );
} }
@Deprecated(since = "6.0") /**
* @deprecated No longer used, should be removed
*/
@Deprecated(since = "6.0", forRemoval = true)
public Iterator<UniqueKey> getUniqueKeyIterator() { public Iterator<UniqueKey> getUniqueKeyIterator() {
return getUniqueKeys().values().iterator(); return getUniqueKeys().values().iterator();
} }
@ -508,10 +518,84 @@ public UniqueKey addUniqueKey(UniqueKey uniqueKey) {
return uniqueKey; return uniqueKey;
} }
/**
* Mark the given column unique.
*/
public void createUniqueKey(Column column, MetadataBuildingContext context) {
final String keyName = context.getBuildingOptions().getImplicitNamingStrategy()
.determineUniqueKeyName( new ImplicitUniqueKeyNameSource() {
@Override
public Identifier getTableName() {
return name;
}
@Override
public List<Identifier> getColumnNames() {
return singletonList( column.getNameIdentifier( context ) );
}
@Override
public Identifier getUserProvidedIdentifier() {
return null;
}
@Override
public MetadataBuildingContext getBuildingContext() {
return context;
}
} )
.render( context.getMetadataCollector().getDatabase().getDialect() );
column.setUniqueKeyName( keyName );
column.setUnique( true );
}
/** /**
* If there is one given column, mark it unique, otherwise * If there is one given column, mark it unique, otherwise
* create a {@link UniqueKey} comprising the given columns. * create a {@link UniqueKey} comprising the given columns.
*/ */
public void createUniqueKey(List<Column> keyColumns, MetadataBuildingContext context) {
if ( keyColumns.size() == 1 ) {
createUniqueKey( keyColumns.get(0), context );
}
else {
final String keyName = context.getBuildingOptions().getImplicitNamingStrategy()
.determineUniqueKeyName( new ImplicitUniqueKeyNameSource() {
@Override
public Identifier getTableName() {
return name;
}
@Override
public List<Identifier> getColumnNames() {
return keyColumns.stream()
.map( column -> column.getNameIdentifier( context ) )
.collect(toList());
}
@Override
public Identifier getUserProvidedIdentifier() {
return null;
}
@Override
public MetadataBuildingContext getBuildingContext() {
return context;
}
} )
.render( context.getMetadataCollector().getDatabase().getDialect() );
final UniqueKey uniqueKey = getOrCreateUniqueKey( keyName );
for ( Column keyColumn : keyColumns ) {
uniqueKey.addColumn( keyColumn );
}
}
}
/**
* If there is one given column, mark it unique, otherwise
* create a {@link UniqueKey} comprising the given columns.
* @deprecated Use {@link #createUniqueKey(List, MetadataBuildingContext)}
*/
@Deprecated(since = "6.5", forRemoval = true)
public void createUniqueKey(List<Column> keyColumns) { public void createUniqueKey(List<Column> keyColumns) {
if ( keyColumns.size() == 1 ) { if ( keyColumns.size() == 1 ) {
keyColumns.get(0).setUnique( true ); keyColumns.get(0).setUnique( true );
@ -540,7 +624,7 @@ public UniqueKey getOrCreateUniqueKey(String keyName) {
return uniqueKey; return uniqueKey;
} }
public void createForeignKeys() { public void createForeignKeys(MetadataBuildingContext context) {
} }
public ForeignKey createForeignKey(String keyName, List<Column> keyColumns, String referencedEntityName, String keyDefinition) { public ForeignKey createForeignKey(String keyName, List<Column> keyColumns, String referencedEntityName, String keyDefinition) {
@ -699,12 +783,18 @@ public void setComment(String comment) {
this.comment = comment; this.comment = comment;
} }
@Deprecated(since = "6.0") /**
* @deprecated No longer used, should be removed
*/
@Deprecated(since = "6.0", forRemoval = true)
public Iterator<String> getCheckConstraintsIterator() { public Iterator<String> getCheckConstraintsIterator() {
return getCheckConstraints().iterator(); return getCheckConstraints().iterator();
} }
@Deprecated(since = "6.2") /**
* @deprecated No longer used, should be removed
*/
@Deprecated(since = "6.2", forRemoval = true)
public List<String> getCheckConstraints() { public List<String> getCheckConstraints() {
return checkConstraints.stream().map( CheckConstraint::getConstraint ).collect( toList() ); return checkConstraints.stream().map( CheckConstraint::getConstraint ).collect( toList() );
} }

View File

@ -47,6 +47,7 @@ public Map<Column, String> getColumnOrderMap() {
return columnOrderMap; return columnOrderMap;
} }
@Deprecated(forRemoval = true)
public String generatedConstraintNamePrefix() { public String generatedConstraintNamePrefix() {
return "UK_"; return "UK_";
} }

View File

@ -7,7 +7,6 @@
package org.hibernate.mapping; package org.hibernate.mapping;
import java.io.Serializable; import java.io.Serializable;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
@ -142,7 +141,7 @@ private Type getIdType(EntityType entityType) {
// called when this is the foreign key of a // called when this is the foreign key of a
// @OneToOne with a FK, or a @OneToMany with // @OneToOne with a FK, or a @OneToMany with
// a join table // a join table
void createUniqueKey(); void createUniqueKey(MetadataBuildingContext context);
boolean isSimpleValue(); boolean isSimpleValue();

View File

@ -9,7 +9,6 @@
import java.util.Locale; import java.util.Locale;
import org.hibernate.boot.Metadata; import org.hibernate.boot.Metadata;
import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.boot.model.relational.Namespace; import org.hibernate.boot.model.relational.Namespace;
import org.hibernate.boot.model.relational.Sequence; import org.hibernate.boot.model.relational.Sequence;
import org.hibernate.boot.model.relational.SqlStringGenerationContext; import org.hibernate.boot.model.relational.SqlStringGenerationContext;
@ -33,6 +32,8 @@
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
import static org.hibernate.boot.model.naming.Identifier.toIdentifier;
/** /**
* Base implementation of {@link SchemaValidator}. * Base implementation of {@link SchemaValidator}.
* *
@ -139,7 +140,9 @@ protected void validateTable(
} }
for ( Column column : table.getColumns() ) { for ( Column column : table.getColumns() ) {
final ColumnInformation existingColumn = tableInformation.getColumn( Identifier.toIdentifier( column.getQuotedName() ) ); final ColumnInformation existingColumn =
//QUESTION: should this use metadata.getDatabase().toIdentifier( column.getQuotedName() )
tableInformation.getColumn( toIdentifier( column.getQuotedName() ) );
if ( existingColumn == null ) { if ( existingColumn == null ) {
throw new SchemaManagementException( throw new SchemaManagementException(
String.format( String.format(

View File

@ -114,7 +114,12 @@ private static void appendConstraints(
Dialect dialect, Dialect dialect,
SqlStringGenerationContext context) { SqlStringGenerationContext context) {
if ( column.isUnique() && !table.isPrimaryKey( column ) ) { if ( column.isUnique() && !table.isPrimaryKey( column ) ) {
final String keyName = Constraint.generateName( "UK_", table, column); String uniqueKeyName = column.getUniqueKeyName();
final String keyName = uniqueKeyName == null
// fallback in case the ImplicitNamingStrategy name was not assigned
// (we don't have access to the ImplicitNamingStrategy here)
? Constraint.generateName( "UK_", table, column )
: uniqueKeyName;
final UniqueKey uniqueKey = table.getOrCreateUniqueKey( keyName ); final UniqueKey uniqueKey = table.getOrCreateUniqueKey( keyName );
uniqueKey.addColumn( column ); uniqueKey.addColumn( column );
definition.append( dialect.getUniqueDelegate().getColumnDefinitionUniquenessFragment( column, context ) ); definition.append( dialect.getUniqueDelegate().getColumnDefinitionUniquenessFragment( column, context ) );

View File

@ -144,7 +144,7 @@ private boolean checkDropConstraint(String tableName, String columnName) throws
if ( getDialect().supportsIfExistsBeforeConstraintName() ) { if ( getDialect().supportsIfExistsBeforeConstraintName() ) {
regex += " if exists"; regex += " if exists";
} }
regex += " uk_.*"; regex += " uk.*";
if ( getDialect().supportsIfExistsAfterConstraintName() ) { if ( getDialect().supportsIfExistsAfterConstraintName() ) {
regex += " if exists"; regex += " if exists";
} }