From 1338ce979ec18e9988ff9ac7fb718c31fd646d0c Mon Sep 17 00:00:00 2001 From: Gerrit Meier Date: Wed, 18 Jan 2023 11:30:10 +0100 Subject: [PATCH] GH-2655 - Fix false-positive cycle detection. If multiple base class extending entities contain the very same target, it was reported as a cycle. Now it will get correctly detected as a directed graph. Closes #2655 --- .../neo4j/core/mapping/DefaultNeo4jPersistentEntity.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/springframework/data/neo4j/core/mapping/DefaultNeo4jPersistentEntity.java b/src/main/java/org/springframework/data/neo4j/core/mapping/DefaultNeo4jPersistentEntity.java index 80a11355f..4f66ec0e0 100644 --- a/src/main/java/org/springframework/data/neo4j/core/mapping/DefaultNeo4jPersistentEntity.java +++ b/src/main/java/org/springframework/data/neo4j/core/mapping/DefaultNeo4jPersistentEntity.java @@ -600,19 +600,24 @@ final class DefaultNeo4jPersistentEntity extends BasicPersistentEntity nodeDescription, Set> visitedNodes, Predicate includeField, PropertyFilter.RelaxedPropertyPath path) { Collection relationships = ((DefaultNeo4jPersistentEntity) nodeDescription).getRelationshipsInHierarchy(includeField, path); + Collection> visitedTargetNodes = new HashSet<>(); for (RelationshipDescription relationship : relationships) { NodeDescription targetNode = relationship.getTarget(); if (visitedNodes.contains(targetNode)) { return true; } - visitedNodes.add(targetNode); - + visitedTargetNodes.add(targetNode); // Branch out again for the sub-tree with all previously visited nodes Set> branchedVisitedNodes = new HashSet<>(visitedNodes); + // Add the already visited target nodes for the next level, + // but don't (!) add them to the visitedNodes yet. + // Otherwise, the same "parallel" defined target nodes will report a false circle. + branchedVisitedNodes.addAll(visitedTargetNodes); if (calculatePossibleCircles(targetNode, branchedVisitedNodes, includeField, path.append(relationship.getFieldName()))) { return true; } } + visitedNodes.addAll(visitedTargetNodes); return false; } }