Logical cyclic mapping dependency

Hi, yesterday I ran into a problem while creating an account in the application I'm currently developing. The console log says:

org.springframework.data.mapping.MappingException: The node with id 5 has a logical cyclic mapping dependency. Its creation caused the creation of another node that has a reference to this.

Classes related:

@Node("Tree")
class Tree(
    @Relationship(type = "OWNS_TREE", direction = Relationship.Direction.INCOMING)
    val owner: Person
) {
    @Id
    @GeneratedValue
    var id: Long = -1

    ...
}
@Node("Person")
class Person(
    var firstName: String,   
    ) {
    @Id
    @GeneratedValue
    var personId: Long = -1

    @Relationship(type = "IS_CHILD_OF", direction = Relationship.Direction.OUTGOING)
    var parents: MutableSet<Person> = mutableSetOf()

    @Relationship(type = "IS_CHILD_OF", direction = Relationship.Direction.INCOMING)
    var children: MutableSet<Person> = mutableSetOf()

    @Relationship(type = "IS_SIBLING_OF")
    var siblings: MutableSet<Person> = mutableSetOf()

    @Relationship(type = "IS_PARTNER_OF")
    var partners: MutableSet<Person> = mutableSetOf()

    @Relationship(type = "OWNS_TREE")
    var ownedTree: Tree? = null

I know that this is because in Person there is a OWNS_TREE relationship, that is also in Tree, which would make it a cyclic dependency, but what does it mean exactly?
The second question is how should I process to having the relationship between mentioned classes that way and working on them without getting that kind of an exception?

The problem is rooted in the dependency chain (cycle) Tree -> Person -> Tree, as you have already discovered.
Spring Data Neo4j has a dead-lock detection during mapping to avoid stack overflow / infinite recursion if it comes to cyclic mapping dependencies. This is why you see the exception.

What happens in detail?

  1. SDN starts mapping the Tree that depends on a Person instance (constructor) and puts it in a set of "objects in construction".
  2. The Person instance gets created AND the properties of it populated. This has to be done because a property can -besides public visibility and setter- also be "set" by using a wither method (Spring Data Neo4j)
  3. The ownedTree property needs the Tree-in-construction -> Exception

To avoid this, you can either remove the constructor dependency or the bi-directional relationship definition.

1 Like