8000 don't create UniqueKeys for Columns with no assigned names · hibernate/hibernate-orm@2f0a34b · GitHub
[go: up one dir, main page]

Skip to content

Commit 2f0a34b

Browse files
committed
don't create UniqueKeys for Columns with no assigned names
1 parent ab0e1e3 commit 2f0a34b

File tree

4 files changed

+60
-15
lines changed

4 files changed

+60
-15
lines changed

hibernate-core/src/main/java/org/hibernate/boot/model/internal/AnnotatedColumn.java

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,8 @@ protected void initMappingColumn(
299299
else {
300300
mappingColumn = new Column();
301301
mappingColumn.setExplicit( !isImplicit );
302-
redefineColumnName( columnName, propertyName, applyNamingStrategy );
302+
final boolean nameDetermined =
303+
inferColumnNameIfPossible( columnName, propertyName, applyNamingStrategy );
303304
mappingColumn.setLength( length );
304305
if ( precision != null && precision > 0 ) { //relevant precision
305306
mappingColumn.setPrecision( precision );
@@ -311,7 +312,12 @@ protected void initMappingColumn(
311312
mappingColumn.setArrayLength( arrayLength );
312313
mappingColumn.setNullable( nullable );
313314
mappingColumn.setSqlType( sqlType );
314-
if ( unique ) {
315+
mappingColumn.setUnique( unique );
316+
// if the column name is not determined, we will assign the
317+
// name to the unique key later this method gets called again
318+
// from linkValueUsingDefaultColumnNaming() in second pass
319+
if ( unique && nameDetermined ) {
320+
// assign a unique key name to the column
315321
getParent().getTable().createUniqueKey( mappingColumn, getBuildingContext() );
316322
}
317323
for ( CheckConstraint constraint : checkConstraints ) {
@@ -341,12 +347,25 @@ public boolean isNameDeferred() {
341347
return mappingColumn == null || isEmpty( mappingColumn.getName() );
342348
}
343349

344-
public void redefineColumnName(String columnName, String propertyName, boolean applyNamingStrategy) {
350+
/**
351+
* Attempt to infer the column name from the explicit {@code name} given by the annotation and the property or field
352+
* name. In the case of a {@link jakarta.persistence.JoinColumn}, this is impossible, due to the rules implemented in
353+
* {@link org.hibernate.boot.model.naming.ImplicitNamingStrategyJpaCompliantImpl#determineJoinColumnName}. In cases
354+
* where the column name cannot be inferred, the {@link Column} is not assigned a name, and this method returns
355+
* {@code false}. The "dummy" {@code Column} will later be replaced with a {@code Column} with a name determined by
356+
* the {@link ImplicitNamingStrategy} when {@link AnnotatedJoinColumn#linkValueUsingDefaultColumnNaming} is called
357+
* during a {@link org.hibernate.boot.spi.SecondPass}.
358+
* @return {@code true} if a name could be inferred
359+
*/
360+
boolean inferColumnNameIfPossible(String columnName, String propertyName, boolean applyNamingStrategy) {
345361
if ( !isEmpty( columnName ) || !isEmpty( propertyName ) ) {
346362
final String logicalColumnName = resolveLogicalColumnName( columnName, propertyName );
347363
mappingColumn.setName( processColumnName( logicalColumnName, applyNamingStrategy ) );
364+
return true;
365+
}
366+
else {
367+
return false;
348368
}
349-
// else nothing to do
350369
}
351370

352371
private String resolveLogicalColumnName(String columnName, String propertyName) {

hibernate-core/src/main/java/org/hibernate/boot/model/internal/AnnotatedJoinColumn.java

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import org.hibernate.AssertionFailure;
99
import org.hibernate.annotations.JoinFormula;
1010
import org.hibernate.boot.model.naming.Identifier;
11+
import org.hibernate.boot.model.naming.ImplicitNamingStrategy;
1112
import org.hibernate.boot.model.naming.ObjectNameNormalizer;
1213
import org.hibernate.boot.model.relational.Database;
1314
import org.hibernate.boot.spi.InFlightMetadataCollector;
@@ -312,6 +313,11 @@ public void copyReferencedStructureAndCreateDefaultJoinColumns(
312313
setMappingColumn( null );
313314
}
314315

316+
/**
317+
* The JPA-specified rules implemented in
318+
* {@link org.hibernate.boot.model.naming.ImplicitNamingStrategyJpaCompliantImpl#determineJoinColumnName}
319+
* prevent us from assigning defaulted names to {@link JoinColumn} until the second pass.
320+
*/
315321
public void linkValueUsingDefaultColumnNaming(
316322
Column referencedColumn,
317323
PersistentClass referencedEntity,
@@ -325,11 +331,15 @@ public void linkValueUsingDefaultColumnNaming(
325331
Column referencedColumn,
326332
PersistentClass referencedEntity,
327333
SimpleValue value) {
334+
// In the case of a reference to a composite primary key,
335+
// this instance of AnnotatedJoinColumn actually represents
336+
// multiple foreign key columns, and this method will be
337+
// called multiple times on the same instance
328338
final String logicalReferencedColumn =
329339
getBuildingContext().getMetadataCollector()
330340
.getLogicalColumnName( referencedEntity.getTable(), referencedColumn.getQuotedName() );
331341
final String columnName = defaultColumnName( columnIndex, referencedEntity, logicalReferencedColumn );
332-
//yuk side effect on an implicit column
342+
// awful side effect on an implicit column
333343
setLogicalColumnName( columnName );
334344
setImplicit( true );
335345
setReferencedColumn( logicalReferencedColumn );
@@ -450,10 +460,23 @@ public void overrideFromReferencedColumnIfNecessary(Column column) {
450460
}
451461
}
452462

463+
/**
464+
* Assign the column name from the explicit {@code name} given by the annotation, if any. In cases where the column
465+
* name cannot be inferred, the {@link Column} is not assigned a name, and this method returns {@code false}. The
466+
* "dummy" {@code Column} will later be replaced with a {@code Column} with name determined by the rules implemented
467+
* in {@link org.hibernate.boot.model.naming.ImplicitNamingStrategyJpaCompliantImpl#determineJoinColumnName},
468+
* as required by the JPA specification, or by any other custom {@link ImplicitNamingStrategy} when
469+
* {@link #linkValueUsingDefaultColumnNaming} is called during a {@link org.hibernate.boot.spi.SecondPass}.
470+
* @return {@code true} if a name could be inferred
471+
*/
453472
@Override
454-
public void redefineColumnName(String columnName, String propertyName, boolean applyNamingStrategy) {
473+
boolean inferColumnNameIfPossible(String columnName, String propertyName, boolean applyNamingStrategy) {
455474
if ( isNotEmpty( columnName ) ) {
456475
getMappingColumn().setName( processColumnName( columnName, applyNamingStrategy ) );
476+
return true;
477+
}
478+
else {
479+
return false;
457480
}
458481
}
459482

hibernate-core/src/main/java/org/hibernate/boot/model/internal/TableBinder.java

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -759,12 +759,13 @@ private static void bindImplicitColumns(
759759
PersistentClass referencedEntity,
760760
AnnotatedJoinColumns joinColumns,
761761
SimpleValue value) {
762-
final KeyValue keyValue = referencedEntity instanceof JoinedSubclass
763-
? referencedEntity.getKey()
764-
: referencedEntity.getIdentifier();
765-
final List<Column> idColumns = keyValue.getColumns();
766-
for ( int i = 0; i < idColumns.size(); i++ ) {
767-
final Column column = idColumns.get(i);
762+
final KeyValue keyValue =
763+
referencedEntity instanceof JoinedSubclass
764+
? referencedEntity.getKey() // a joined subclass is referenced via the key of the subclass table
765+
: referencedEntity.getIdentifier();
766+
final List<Column> referencedKeyColumns = keyValue.getColumns();
767+
for ( int i = 0; i < referencedKeyColumns.size(); i++ ) {
768+
final Column column = referencedKeyColumns.get(i);
768769
final AnnotatedJoinColumn firstColumn = joinColumns.getJoinColumns().get(0);
769770
firstColumn.linkValueUsingDefaultColumnNaming( i, column, referencedEntity, value );
770771
firstColumn.overrideFromReferencedColumnIfNecessary( column );

hibernate-core/src/main/java/org/hibernate/mapping/Table.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -469,7 +469,7 @@ public Index getIndex(String indexName) {
469469
}
470470

471471
public Index addIndex(Index index) {
472-
Index current = indexes.get( index.getName() );
472+
final Index current = indexes.get( index.getName() );
473473
if ( current != null ) {
474474
throw new MappingException( "Index " + index.getName() + " already exists" );
475475
}
@@ -478,7 +478,7 @@ public Index addIndex(Index index) {
478478
}
479479

480480
public UniqueKey addUniqueKey(UniqueKey uniqueKey) {
481-
UniqueKey current = uniqueKeys.get( uniqueKey.getName() );
481+
final UniqueKey current = uniqueKeys.get( uniqueKey.getName() );
482482
if ( current != null ) {
483483
throw new MappingException( "UniqueKey " + uniqueKey.getName() + " already exists" );
484484
}
@@ -487,7 +487,9 @@ public UniqueKey addUniqueKey(UniqueKey uniqueKey) {
487487
}
488488

489489
/**
490-
* Mark the given column unique.
490+
* Mark the given column unique and assign a name to the unique key.
491+
* <p>
492+
* This method does not add a {@link UniqueKey} to the table itself!
491493
*/
492494
public void createUniqueKey(Column column, MetadataBuildingContext context) {
493495
final String keyName = context.getBuildingOptions().getImplicitNamingStrategy()

0 commit comments

Comments
 (0)
0