spring-projects / spring-data-neo4j

Provide support to increase developer productivity in Java when using Neo4j. Uses familiar Spring concepts such as a template classes for core API usage and lightweight repository style data access.
http://spring.io/projects/spring-data-neo4j
Apache License 2.0
815 stars 616 forks source link

Domain Cycles order of mapping causes loss of information using projections #2917

Open NilsWild opened 3 days ago

NilsWild commented 3 days ago

I ran into an issue that might be closely related to https://github.com/spring-projects/spring-data-neo4j/issues/2858 This time regarding writing to the database instead of query from the database.

Given an Entity that has a Set of other Entities and these other Entities can have relationships to each other. When i try to store them i use projections to avoid infinite recursion. The references between the other Entities are projected using a simple EntityReferenceProjection that contains just the id and version.

I guess the Problem is, that the each entity (by id) is only mapped once.

To make it more easy to understand i provide an example with three test cases: https://github.com/NilsWild/spring-issue-demo/tree/7eda1ab2405e6810c639768d5d72e2180641bb2c

Test Cases: save and retrieve map b2 first <- Issue b1 is referenced in b2 before b1 is stored, thus b1 is mapped with the incompletely populated reference entity save and retrieve map b2 first with reference to b1 completely populated <- same as "save and retrieve map b2 first" but the entity is completely populated even in the EntityReference save and retrieve map b1 first <- Same as "save and retrieve map b2 first" but this time b1 is the first element in the set. Thus the completely populated entity is used for persistence

meistermeier commented 2 days ago

Maybe I am missing something here but shouldn't this somehow be expected? In the failing test case, the real B1 gets stored after the chain B2->B1' got already persisted. In this case SDN knows that it already has processed B1 (because B1' has the same id) and will skip it and its label property. The test with the other ordering of Bs will persist B1 and skip the B1' that is part of B2->B1'. In this case the label from the original B1 is already persisted.

What you want, and please correct me if I am wrong: Spring Data Neo4j would have to aggregate all same types(nodes) with the same ids first and create a merge of those objects. This is not how SDN works but it processes (save, update) entities when they appear directly. Putting this general conflict with the workflow aside, adding such a merge logic seems clean for new objects but what if there are conflicting information? Let's say label1 in one entity and label2 in the other.

Maybe your example is oversimplified but right now I tend to say that this is something we won't introduce.