fix issue with circularity detection

This commit is contained in:
Andrea Boriero 2020-02-20 10:38:13 +00:00
parent 1df4824d5f
commit 90cd4e5c8f
6 changed files with 40 additions and 60 deletions

View File

@ -13,10 +13,4 @@ import org.hibernate.sql.results.graph.Fetchable;
*/
public interface Association extends Fetchable {
ForeignKeyDescriptor getForeignKeyDescriptor();
/**
* The column expressions that identify this association.
* Mainly used in circularity detection
*/
String[] getIdentifyingColumnExpressions();
}

View File

@ -47,7 +47,6 @@ public class EntityCollectionPart
private final EntityMappingType entityMappingType;
private ModelPart fkTargetModelPart;
private String[] identifyingColumns;
@SuppressWarnings("WeakerAccess")
public EntityCollectionPart(
@ -75,14 +74,6 @@ public class EntityCollectionPart
else {
fkTargetModelPart = entityMappingType.findSubPart( fkTargetModelPartName, null );
}
final List<String> identifyingColumnsList = new ArrayList<>();
collectionDescriptor.getAttributeMapping().getKeyDescriptor().visitReferringColumns(
(containingTableExpression, columnExpression, jdbcMapping) -> {
identifyingColumnsList.add( containingTableExpression + "." + columnExpression );
}
);
this.identifyingColumns = identifyingColumnsList.toArray( new String[0] );
}
@ -212,9 +203,4 @@ public class EntityCollectionPart
// todo (6.0) : this will not strictly work - we'd want a new ForeignKeyDescriptor that points the other direction
return collectionDescriptor.getAttributeMapping().getKeyDescriptor();
}
@Override
public String[] getIdentifyingColumnExpressions() {
return identifyingColumns;
}
}

View File

@ -8,6 +8,7 @@ package org.hibernate.metamodel.mapping.internal;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.function.Consumer;
import org.hibernate.HibernateException;
@ -57,6 +58,7 @@ public class SimpleForeignKeyDescriptor implements ForeignKeyDescriptor, BasicVa
private final String targetColumnExpression;
private final JdbcMapping jdbcMapping;
private final ForeignKeyDirection fKeyDirection;
private final int hasCode;
public SimpleForeignKeyDescriptor(
ForeignKeyDirection fKeyDirection,
@ -71,6 +73,13 @@ public class SimpleForeignKeyDescriptor implements ForeignKeyDescriptor, BasicVa
this.targetColumnContainingTable = targetColumnContainingTable;
this.targetColumnExpression = targetColumnExpression;
this.jdbcMapping = jdbcMapping;
this.hasCode = Objects.hash(
keyColumnContainingTable,
keyColumnExpression,
targetColumnContainingTable,
targetColumnExpression
);
}
@Override
@ -405,4 +414,24 @@ public class SimpleForeignKeyDescriptor implements ForeignKeyDescriptor, BasicVa
public String getTargetColumnExpression() {
return targetColumnExpression;
}
@Override
public boolean equals(Object o) {
if ( this == o ) {
return true;
}
if ( o == null || getClass() != o.getClass() ) {
return false;
}
SimpleForeignKeyDescriptor that = (SimpleForeignKeyDescriptor) o;
return Objects.equals( keyColumnContainingTable, that.keyColumnContainingTable ) &&
Objects.equals( targetColumnContainingTable, that.targetColumnContainingTable ) &&
Objects.equals( keyColumnExpression, that.keyColumnExpression ) &&
Objects.equals( targetColumnExpression, that.targetColumnExpression );
}
@Override
public int hashCode() {
return this.hasCode;
}
}

View File

@ -6,10 +6,6 @@
*/
package org.hibernate.metamodel.mapping.internal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.NotYetImplementedFor6Exception;
@ -81,11 +77,6 @@ public class SingularAssociationAttributeMapping extends AbstractSingularAttribu
private ForeignKeyDescriptor foreignKeyDescriptor;
private String identifyingColumnsTableExpression;
private String inverseIdentifyingColumnsTableExpression;
private String[] identifyingColumns;
public SingularAssociationAttributeMapping(
String name,
@ -139,30 +130,14 @@ public class SingularAssociationAttributeMapping extends AbstractSingularAttribu
this.foreignKeyDescriptor = foreignKeyDescriptor;
final String identifyingColumnsTableExpression;
final String inverseColumnsTableExpression;
final List<String> identifyingColumnsList = new ArrayList<>();
if ( foreignKeyDescriptor.getDirection() == ForeignKeyDirection.FROM_PARENT && !referringPrimaryKey ) {
identifyingColumnsTableExpression = foreignKeyDescriptor.getTargetTableExpression();
inverseColumnsTableExpression = foreignKeyDescriptor.getReferringTableExpression();
foreignKeyDescriptor.visitTargetColumns(
(containingTableExpression, columnExpression, jdbcMapping) -> {
identifyingColumnsList.add( containingTableExpression + "." + columnExpression );
}
);
}
else {
identifyingColumnsTableExpression = foreignKeyDescriptor.getReferringTableExpression();
inverseColumnsTableExpression = foreignKeyDescriptor.getTargetTableExpression();
foreignKeyDescriptor.visitReferringColumns(
(containingTableExpression, columnExpression, jdbcMapping) -> {
identifyingColumnsList.add( containingTableExpression + "." + columnExpression );
}
);
}
this.identifyingColumns = identifyingColumnsList.toArray( new String[0] );
this.identifyingColumnsTableExpression = identifyingColumnsTableExpression;
this.inverseIdentifyingColumnsTableExpression = inverseColumnsTableExpression;
}
public ForeignKeyDescriptor getForeignKeyDescriptor() {
@ -188,11 +163,6 @@ public class SingularAssociationAttributeMapping extends AbstractSingularAttribu
return navigableRole;
}
@Override
public String[] getIdentifyingColumnExpressions() {
return identifyingColumns;
}
@Override
public Fetch resolveCircularFetch(
NavigablePath fetchablePath,
@ -218,7 +188,7 @@ public class SingularAssociationAttributeMapping extends AbstractSingularAttribu
final Association associationParent = (Association) referencedModePart;
if ( Arrays.equals( associationParent.getIdentifyingColumnExpressions(), this.getIdentifyingColumnExpressions() ) ) {
if (foreignKeyDescriptor.equals( associationParent.getForeignKeyDescriptor() ) ) {
// we need to determine the NavigablePath referring to the entity that the bi-dir
// fetch will "return" for its Assembler. so we walk "up" the FetchParent graph
// to find the "referenced entity" reference

View File

@ -52,14 +52,22 @@ public class Helper {
if ( ResultsLogger.INSTANCE.isDebugEnabled() ) {
return initializer -> {
ResultsLogger.INSTANCE.debug( "Adding initializer : " + initializer );
initializers.add( initializer );
addIfNotPresent( initializers, initializer );
};
}
else {
return initializers::add;
return initializer ->
addIfNotPresent( initializers, initializer );
}
}
private static void addIfNotPresent(List<Initializer> initializers, Initializer initializer) {
if ( initializers.contains( initializer ) ) {
return;
}
initializers.add( initializer );
}
public static void finalizeCollectionLoading(
PersistenceContext persistenceContext,
CollectionPersister collectionDescriptor,

View File

@ -155,13 +155,6 @@ public class BiDirectionalFetchImpl implements BiDirectionalFetch, Association {
return ( (Association) fetchParent ).getForeignKeyDescriptor();
}
@Override
public String[] getIdentifyingColumnExpressions() {
// fetch parent really always needs to be an Association, so we simply cast here
// should maybe verify this in ctor
return ( (Association) fetchParent ).getIdentifyingColumnExpressions();
}
@Override
public Fetch generateFetch(
FetchParent fetchParent,