light refactoring

This commit is contained in:
Gavin 2022-11-25 19:34:03 +01:00 committed by Gavin King
parent 3ba90c004c
commit 13f4c8c285
3 changed files with 242 additions and 186 deletions

View File

@ -1931,45 +1931,8 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector
Identifier nameIdentifier; Identifier nameIdentifier;
ImplicitForeignKeyNameSource foreignKeyNameSource = new ImplicitForeignKeyNameSource() { nameIdentifier = getMetadataBuildingOptions().getImplicitNamingStrategy()
final List<Identifier> columnNames = extractColumnNames( foreignKey.getColumns() ); .determineForeignKeyName( new ForeignKeyNameSource( foreignKey, table, buildingContext ) );
List<Identifier> 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;
}
};
nameIdentifier = getMetadataBuildingOptions().getImplicitNamingStrategy().determineForeignKeyName(foreignKeyNameSource);
foreignKey.setName( nameIdentifier.render( getDatabase().getJdbcEnvironment().getDialect() ) ); foreignKey.setName( nameIdentifier.render( getDatabase().getJdbcEnvironment().getDialect() ) );
@ -2063,127 +2026,116 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector
//column equals and hashcode is based on column name //column equals and hashcode is based on column name
} }
catch ( MappingException e ) { catch ( MappingException e ) {
// If at least 1 columnName does exist, 'columns' will contain a mix of Columns and nulls. In order // If at least 1 columnName does exist, 'columns' will contain a mix of Columns and nulls.
// to exhaustively report all of the unbound columns at once, w/o an NPE in // In order to exhaustively report all the unbound columns at once, w/o an NPE in
// Constraint#generateName's array sorting, simply create a fake Column. // Constraint#generateName's array sorting, simply create a fake Column.
columns[index] = new Column( logicalColumnName ); columns[index] = new Column( logicalColumnName );
unboundNoLogical.add( columns[index] ); unboundNoLogical.add( columns[index] );
} }
} }
final String originalKeyName = keyName; createIndexOrUniqueKey( table, keyName, nameExplicit, columnNames, orderings, unique, buildingContext, columns, unbound );
if ( unique ) {
final Identifier keyNameIdentifier = getMetadataBuildingOptions().getImplicitNamingStrategy().determineUniqueKeyName(
new ImplicitUniqueKeyNameSource() {
@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;
}
}
);
keyName = keyNameIdentifier.render( getDatabase().getJdbcEnvironment().getDialect() );
UniqueKey uk = table.getOrCreateUniqueKey( keyName );
uk.setNameExplicit( nameExplicit );
for ( int i = 0; i < columns.length; i++ ) {
Column column = columns[i];
String order = orderings != null ? orderings[i] : null;
if ( table.containsColumn( column ) ) {
uk.addColumn( column, order );
unbound.remove( column );
}
}
}
else {
final Identifier keyNameIdentifier = getMetadataBuildingOptions().getImplicitNamingStrategy().determineIndexName(
new ImplicitIndexNameSource() {
@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;
}
}
);
keyName = keyNameIdentifier.render( getDatabase().getJdbcEnvironment().getDialect() );
Index index = table.getOrCreateIndex( keyName );
for ( int i = 0; i < columns.length; i++ ) {
Column column = columns[i];
String order = orderings != null ? orderings[i] : null;
if ( table.containsColumn( column ) ) {
index.addColumn( column, order );
unbound.remove( column );
}
}
}
if ( unbound.size() > 0 || unboundNoLogical.size() > 0 ) { if ( unbound.size() > 0 || unboundNoLogical.size() > 0 ) {
StringBuilder sb = new StringBuilder( "Unable to create " ); throwUnableToCreateConstraint( table, columnNames, unique, unbound, unboundNoLogical );
if ( unique ) {
sb.append( "unique key constraint (" );
}
else {
sb.append( "index (" );
}
for ( String columnName : columnNames ) {
sb.append( columnName ).append( ", " );
}
sb.setLength( sb.length() - 2 );
sb.append( ") on table '" ).append( table.getName() ).append( "' since the column " );
for ( Column column : unbound ) {
sb.append("'").append( column.getName() ).append( "', " );
}
for ( Column column : unboundNoLogical ) {
sb.append("'").append( column.getName() ).append( "', " );
}
sb.setLength( sb.length() - 2 );
sb.append( " was not found (specify the correct column name, which depends on the naming strategy, and may not be the same as the entity property name)" );
throw new AnnotationException( sb.toString() );
} }
} }
private void createIndexOrUniqueKey(
Table table,
String originalKeyName,
boolean nameExplicit,
String[] columnNames,
String[] orderings,
boolean unique,
MetadataBuildingContext buildingContext,
Column[] columns,
Set<Column> unbound) {
if (unique) {
createUniqueKey( table, originalKeyName, nameExplicit, columnNames, orderings, buildingContext, columns, unbound );
}
else {
createIndex( table, originalKeyName, columnNames, orderings, buildingContext, columns, unbound );
}
}
private void createIndex(
Table table,
String originalKeyName,
String[] columnNames,
String[] orderings,
MetadataBuildingContext buildingContext,
Column[] columns,
Set<Column> unbound) {
final Identifier keyNameIdentifier = getMetadataBuildingOptions().getImplicitNamingStrategy()
.determineIndexName( new IndexOrUniqueKeyNameSource( buildingContext, table, columnNames, originalKeyName ) );
final String keyName = keyNameIdentifier.render( getDatabase().getJdbcEnvironment().getDialect() );
final Index index = table.getOrCreateIndex( keyName );
for (int i = 0; i < columns.length; i++ ) {
Column column = columns[i];
String order = orderings != null ? orderings[i] : null;
if ( table.containsColumn( column ) ) {
index.addColumn( column, order );
unbound.remove( column );
}
}
}
private void createUniqueKey(
Table table,
String originalKeyName,
boolean nameExplicit,
String[] columnNames,
String[] orderings,
MetadataBuildingContext buildingContext,
Column[] columns,
Set<Column> unbound) {
final Identifier keyNameIdentifier = getMetadataBuildingOptions().getImplicitNamingStrategy()
.determineUniqueKeyName( new IndexOrUniqueKeyNameSource( buildingContext, table, columnNames, originalKeyName ) );
final String keyName = keyNameIdentifier.render( getDatabase().getJdbcEnvironment().getDialect() );
final UniqueKey uk = table.getOrCreateUniqueKey( keyName );
uk.setNameExplicit(nameExplicit);
for (int i = 0; i < columns.length; i++ ) {
Column column = columns[i];
String order = orderings != null ? orderings[i] : null;
if ( table.containsColumn( column ) ) {
uk.addColumn( column, order );
unbound.remove( column );
}
}
}
private static void throwUnableToCreateConstraint(
Table table,
String[] columnNames,
boolean unique,
Set<Column> unbound,
Set<Column> unboundNoLogical) {
final StringBuilder message = new StringBuilder( "Unable to create " );
if (unique) {
message.append( "unique key constraint (" );
}
else {
message.append( "index (" );
}
for ( String columnName : columnNames) {
message.append( columnName ).append( ", " );
}
message.setLength( message.length() - 2 );
message.append( ") on table '" ).append( table.getName() ).append( "' since the column " );
for ( Column column : unbound) {
message.append("'").append( column.getName() ).append( "', " );
}
for ( Column column : unboundNoLogical) {
message.append("'").append( column.getName() ).append( "', " );
}
message.setLength( message.length() - 2 );
message.append( " was not found (specify the correct column name, which depends on the naming strategy, and may not be the same as the entity property name)" );
throw new AnnotationException( message.toString() );
}
private void processJPAIndexHolders(MetadataBuildingContext buildingContext) { private void processJPAIndexHolders(MetadataBuildingContext buildingContext) {
if ( jpaIndexHoldersByTable == null ) { if ( jpaIndexHoldersByTable == null ) {
return; return;
@ -2379,4 +2331,93 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector
} }
return identifier.render( dialect ); return identifier.render( dialect );
} }
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 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

@ -2638,47 +2638,62 @@ public abstract class CollectionBinder {
SimpleValue value, SimpleValue value,
boolean unique) { boolean unique) {
if ( hasMappedBy() ) { if ( hasMappedBy() ) {
final Property property = targetEntity.getRecursiveProperty( mappedBy ); bindUnownedManyToManyInverseForeignKey( targetEntity, joinColumns, value );
final List<Selectable> mappedByColumns = mappedByColumns( targetEntity, property );
final AnnotatedJoinColumn firstColumn = joinColumns.getJoinColumns().get(0);
for ( Selectable selectable: mappedByColumns ) {
firstColumn.linkValueUsingAColumnCopy( (Column) selectable, value );
}
final String referencedPropertyName = buildingContext.getMetadataCollector()
.getPropertyReferencedAssociation( targetEntity.getEntityName(), mappedBy );
if ( referencedPropertyName != null ) {
//TODO always a many to one?
( (ManyToOne) value ).setReferencedPropertyName( referencedPropertyName );
buildingContext.getMetadataCollector()
.addUniquePropertyReference( targetEntity.getEntityName(), referencedPropertyName );
}
( (ManyToOne) value ).setReferenceToPrimaryKey( referencedPropertyName == null );
value.createForeignKey();
} }
else { else {
createSyntheticPropertyReference( bindOwnedManyToManyForeignKeyMappedBy( targetEntity, joinColumns, value, unique );
joinColumns,
targetEntity,
collection.getOwner(),
value,
propertyName,
true,
buildingContext
);
if ( notFoundAction == NotFoundAction.IGNORE ) {
value.disableForeignKey();
}
TableBinder.bindForeignKey(
targetEntity,
collection.getOwner(),
joinColumns,
value,
unique,
buildingContext
);
} }
} }
private void bindOwnedManyToManyForeignKeyMappedBy(
PersistentClass targetEntity,
AnnotatedJoinColumns joinColumns,
SimpleValue value,
boolean unique) { // true when it's actually a logical @OneToMany
createSyntheticPropertyReference(
joinColumns,
targetEntity,
collection.getOwner(),
value,
propertyName,
true,
buildingContext
);
if ( notFoundAction == NotFoundAction.IGNORE ) {
value.disableForeignKey();
}
TableBinder.bindForeignKey(
targetEntity,
collection.getOwner(),
joinColumns,
value,
unique,
buildingContext
);
}
private void bindUnownedManyToManyInverseForeignKey(
PersistentClass targetEntity,
AnnotatedJoinColumns joinColumns,
SimpleValue value) {
final Property property = targetEntity.getRecursiveProperty( mappedBy );
final List<Selectable> mappedByColumns = mappedByColumns(targetEntity, property );
final AnnotatedJoinColumn firstColumn = joinColumns.getJoinColumns().get(0);
for ( Selectable selectable: mappedByColumns ) {
firstColumn.linkValueUsingAColumnCopy( (Column) selectable, value);
}
final String referencedPropertyName = buildingContext.getMetadataCollector()
.getPropertyReferencedAssociation( targetEntity.getEntityName(), mappedBy );
if ( referencedPropertyName != null ) {
//TODO always a many to one?
( (ManyToOne) value).setReferencedPropertyName( referencedPropertyName );
buildingContext.getMetadataCollector()
.addUniquePropertyReference( targetEntity.getEntityName(), referencedPropertyName );
}
( (ManyToOne) value).setReferenceToPrimaryKey( referencedPropertyName == null );
value.createForeignKey();
}
private static List<Selectable> mappedByColumns(PersistentClass referencedEntity, Property property) { private static List<Selectable> mappedByColumns(PersistentClass referencedEntity, Property property) {
if ( property.getValue() instanceof Collection ) { if ( property.getValue() instanceof Collection ) {
return ( (Collection) property.getValue() ).getKey().getSelectables(); return ( (Collection) property.getValue() ).getKey().getSelectables();

View File

@ -20,7 +20,7 @@ import org.hibernate.internal.util.StringHelper;
*/ */
public class UniqueKey extends Constraint { public class UniqueKey extends Constraint {
private final Map<Column, String> columnOrderMap = new HashMap<>(); private final Map<Column, String> columnOrderMap = new HashMap<>();
private boolean nameExplicit; private boolean nameExplicit; // true when the constraint name was explicitly specified by @UniqueConstraint annotation
@Override @Deprecated(since="6.2") @Override @Deprecated(since="6.2")
public String sqlConstraintString( public String sqlConstraintString(