Skip to content

Commit e045ddf

Browse files
committed
GH-2514 - Avoid non-immutable property mapping recursion.
Closes #2514
1 parent 52e9a5e commit e045ddf

File tree

2 files changed

+31
-1
lines changed

2 files changed

+31
-1
lines changed

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

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -587,7 +587,14 @@ private Optional<Object> createInstanceOfRelationships(Neo4jPersistentProperty p
587587
for (Relationship possibleRelationship : allMatchingTypeRelationshipsInResult) {
588588
if (targetIdSelector.apply(possibleRelationship) == targetNodeId) {
589589

590-
Object mappedObject = map(possibleValueNode, concreteTargetNodeDescription, null, relationshipsFromResult, nodesFromResult);
590+
// If the target is the same(equal) node, get the related object from the cache.
591+
// Avoiding the call to the map method also breaks an endless cycle of trying to finish
592+
// the property population of _this_ object.
593+
// The initial population will happen at the end of this mapping. This is sufficient because
594+
// it only affects properties not changing the instance of the object.
595+
Object mappedObject = sourceNodeId != null && sourceNodeId.equals(targetNodeId)
596+
? knownObjects.getObject(sourceNodeId)
597+
: map(possibleValueNode, concreteTargetNodeDescription, null, relationshipsFromResult, nodesFromResult);
591598
if (relationshipDescription.hasRelationshipProperties()) {
592599

593600
Object relationshipProperties = map(possibleRelationship,

src/test/java/org/springframework/data/neo4j/integration/imperative/RepositoryIT.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -824,6 +824,24 @@ void findPageByCustomQueryWithCountShouldWork(@Autowired PersonRepository reposi
824824
assertThat(slice.getTotalElements()).isEqualTo(2);
825825
assertThat(slice.getTotalPages()).isEqualTo(2);
826826
}
827+
828+
@Test
829+
void findEntityPointingToEqualEntity(@Autowired PetRepository repository) {
830+
doWithSession(session ->
831+
session
832+
.run("CREATE (:Pet{name: 'Pet2'})-[:Has]->(p1:Pet{name: 'Pet1'})-[:Has]->(p1) RETURN p1")
833+
.consume());
834+
835+
List<Pet> allPets = repository.findAllFriends();
836+
for (Pet pet : allPets) {
837+
// everybody has a friend
838+
assertThat(pet.getFriends()).hasSize(1);
839+
// but only Pet1 is its own best friend
840+
if (pet.getName().equals("Pet1")) {
841+
assertThat(pet.getFriends().get(0)).isEqualTo(pet);
842+
}
843+
}
844+
}
827845
}
828846

829847
@Nested
@@ -4149,6 +4167,11 @@ interface PetRepository extends Neo4jRepository<Pet, Long> {
41494167

41504168
@Query("MATCH (n:Pet) where n.name='Luna' OPTIONAL MATCH (n)-[r:Has]->(m:Pet) return n, collect(r), collect(m)")
41514169
List<Pet> findLunas();
4170+
4171+
@Query("MATCH (p:Pet)"
4172+
+ " OPTIONAL MATCH (p)-[rel:Has]->(op)"
4173+
+ " RETURN p, collect(rel), collect(op)")
4174+
List<Pet> findAllFriends();
41524175
}
41534176

41544177
interface ImmutablePetRepository extends Neo4jRepository<ImmutablePet, Long> {

0 commit comments

Comments
 (0)