Skip to content

Commit 7a8b10b

Browse files
michael-simonsma-ku
andcommitted
fix: Use direction as part of the node collection name for each relationship.
This avoids having duplicate keys in the map projection used to collect the nodes for each relationship in cases where a node has two relationships with the same name to the same label in different directions. Fixes #2918. Co-authored-by: Mathias Kühn <[email protected]>
1 parent 5f07659 commit 7a8b10b

File tree

6 files changed

+144
-1
lines changed

6 files changed

+144
-1
lines changed

src/main/java/org/springframework/data/neo4j/core/mapping/RelationshipDescription.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ default boolean isIncoming() {
117117
@NonNull
118118
default String generateRelatedNodesCollectionName(NodeDescription<?> mostAbstractNodeDescription) {
119119

120-
return this.getSource().getMostAbstractParentLabel(mostAbstractNodeDescription) + "_" + this.getType() + "_" + this.getTarget().getPrimaryLabel();
120+
return this.getSource().getMostAbstractParentLabel(mostAbstractNodeDescription) + "_" + this.getType() + "_" + this.getTarget().getPrimaryLabel() + "_" + this.isOutgoing();
121121
}
122122

123123
/**

src/test/java/org/springframework/data/neo4j/integration/issues/IssuesIT.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import static org.assertj.core.api.Assertions.as;
1919
import static org.assertj.core.api.Assertions.assertThat;
2020
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
21+
import static org.assertj.core.api.Assertions.assertThatNoException;
2122
import static org.assertj.core.api.Assertions.tuple;
2223

2324
import java.util.ArrayList;
@@ -169,6 +170,8 @@
169170
import org.springframework.data.neo4j.integration.issues.gh2906.FromRepository;
170171
import org.springframework.data.neo4j.integration.issues.gh2906.OutgoingBugRelationship;
171172
import org.springframework.data.neo4j.integration.issues.gh2906.ToRepository;
173+
import org.springframework.data.neo4j.integration.issues.gh2918.ConditionNode;
174+
import org.springframework.data.neo4j.integration.issues.gh2918.ConditionRepository;
172175
import org.springframework.data.neo4j.integration.issues.qbe.A;
173176
import org.springframework.data.neo4j.integration.issues.qbe.ARepository;
174177
import org.springframework.data.neo4j.integration.issues.qbe.B;
@@ -1557,6 +1560,18 @@ private static void assertGH2906Graph(Driver driver, int cnt) {
15571560
});
15581561
}
15591562

1563+
@Test
1564+
@Tag("GH-2918")
1565+
void loadCycleFreeWithInAndOutgoingRelationship(@Autowired ConditionRepository conditionRepository, @Autowired Driver driver) {
1566+
1567+
var conditionSaved = conditionRepository.save(new ConditionNode());
1568+
1569+
// Condition has both an incoming and outgoing relationship typed CAUSES that will cause a duplicate key
1570+
// in the map projection for the relationships to load. The fix was to indicate the direction in the name
1571+
// used for projecting the relationship, too
1572+
assertThatNoException().isThrownBy(() -> conditionRepository.findById(conditionSaved.uuid));
1573+
}
1574+
15601575
@Configuration
15611576
@EnableTransactionManagement
15621577
@EnableNeo4jRepositories(namedQueriesLocation = "more-custom-queries.properties")
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* Copyright 2011-2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.neo4j.integration.issues.gh2918;
17+
18+
import java.util.Set;
19+
20+
import org.springframework.data.neo4j.core.schema.GeneratedValue;
21+
import org.springframework.data.neo4j.core.schema.Id;
22+
import org.springframework.data.neo4j.core.schema.Node;
23+
import org.springframework.data.neo4j.core.schema.Relationship;
24+
import org.springframework.data.neo4j.core.support.UUIDStringGenerator;
25+
26+
/**
27+
* @author Mathias Kühn
28+
*/
29+
@Node
30+
public class ConditionNode {
31+
@Id
32+
@GeneratedValue(UUIDStringGenerator.class)
33+
public String uuid;
34+
35+
@Relationship(type = "CAUSES", direction = Relationship.Direction.INCOMING)
36+
public Set<FailureRelationship> upstreamFailures;
37+
38+
@Relationship(type = "CAUSES", direction = Relationship.Direction.OUTGOING)
39+
public Set<FailureRelationship> downstreamFailures;
40+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*
2+
* Copyright 2011-2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.neo4j.integration.issues.gh2918;
17+
18+
import org.springframework.data.neo4j.repository.Neo4jRepository;
19+
20+
/**
21+
* @author Mathias Kühn
22+
*/
23+
public interface ConditionRepository extends Neo4jRepository<ConditionNode, String> {
24+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* Copyright 2011-2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.neo4j.integration.issues.gh2918;
17+
18+
import org.springframework.data.neo4j.core.schema.GeneratedValue;
19+
import org.springframework.data.neo4j.core.schema.Id;
20+
import org.springframework.data.neo4j.core.schema.Node;
21+
import org.springframework.data.neo4j.core.support.UUIDStringGenerator;
22+
23+
/**
24+
* @author Mathias Kühn
25+
*/
26+
@Node
27+
public class FailureNode {
28+
@Id
29+
@GeneratedValue(UUIDStringGenerator.class)
30+
public String uuid;
31+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* Copyright 2011-2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.neo4j.integration.issues.gh2918;
17+
18+
import org.springframework.data.neo4j.core.schema.RelationshipId;
19+
import org.springframework.data.neo4j.core.schema.RelationshipProperties;
20+
import org.springframework.data.neo4j.core.schema.TargetNode;
21+
22+
/**
23+
* @author Mathias Kühn
24+
*/
25+
@RelationshipProperties
26+
public abstract class FailureRelationship {
27+
28+
@RelationshipId
29+
public String id;
30+
31+
@TargetNode
32+
public FailureNode target;
33+
}

0 commit comments

Comments
 (0)