title: How Spring Data Neo4j abstraction handles creation & update (repository.save)
body: <p>For the purposes of testing, I created a simple domain in the form of a tree of companies and their orders, so:</p>
  <ul>
  <li>company delivers orders</li>
  <li>company has only one company above</li>
  <li>company can have multiple collectors below</li>
  </ul>
  <p>And this is how I represented it:</p>
  <pre><code>@Node
  public class Company {
  
      @Id
      @GeneratedValue(UUIDStringGenerator.class)
      private String id;
  
      private String name;
  
      @Relationship(type = &quot;COLLECTS_FROM&quot;, direction = INCOMING)
      private Company parent;
  
      @Relationship(type = &quot;COLLECTS_FROM&quot;)
      private Set&lt;Company&gt; children;
  
      @Relationship(type = &quot;DELIVERS&quot;)
      private Set&lt;Order&gt; orders;
  
      //all args constructor with (thid.id = null)
      //getters and setters (omitted for brevity)
  }   
  
  @Node
  public class Order {
  
      @Id
      @GeneratedValue(UUIDStringGenerator.class)
      private String id;
      private final String partNumber;
      private final Integer quantityOrdered;
      private final Integer quantityReceived;
      
      //all args constructor with (thid.id = null)
      //getters and setters (omitted for brevity)
  </code></pre>
  <p>Of course, I have two very simple repositories:</p>
  <pre><code>@Repository
  public interface CompanyRepository extends Neo4jRepository&lt;Company, String&gt; {
  }
  @Repository
  public interface OrderRepository extends Neo4jRepository&lt;Order, String&gt; {
  }
  </code></pre>
  <p>I created few integration tests:</p>
  <pre><code>    @Test
      void shouldCreateCompanyWithRelations() {
          Company parent = companyRepository.save(new Company(&quot;parent&quot;, null, null, null));
          Company firstChild = companyRepository.save(new Company(&quot;Child1&quot;, null, null, null));
          Company secondChild = companyRepository.save(new Company(&quot;Child2&quot;, null, null, null));
          Order firstOrder = orderRepository.save(new Order(&quot;part1&quot;, 10, 10));
          Order secondOrder = orderRepository.save(new Order(&quot;part2&quot;, 20, 20));
          Company testCompany = companyRepository.save(new Company(&quot;TestCompany&quot;, parent, Set.of(firstChild, secondChild), Set.of(firstOrder, secondOrder)));
  
          var result = companyRepository.findById(testCompany.getId());
  
          assertThat(result)
                  .hasValueSatisfying(company -&gt; {
                      assertThat(company.getId()).isNotNull();
                      assertThat(company.getName()).isEqualTo(&quot;TestCompany&quot;);
                      assertThat(company.getParent()).isNotNull(); //this assertion fails, returns null
                      assertThat(company.getChildren()).hasSize(2); //this assertion fails, returns 0
                      assertThat(company.getOrders()).hasSize(2);
                  });
      }
  </code></pre>
  <ul>
  <li>Expectation: all relations will be created.</li>
  <li>Reality: test fails due to missing relation to <code>parent</code> &amp; <code>children</code> (same node), relation to orders exist (different node)</li>
  </ul>
  <pre><code>    @Test
      void createWithSingleSave() {
          Company parent = new Company(&quot;parent&quot;, null, null, null);
          Company firstChild = new Company(&quot;Child1&quot;, null, null, null);
          Company secondChild = new Company(&quot;Child2&quot;, null, null, null);
          Order firstOrder = new Order(&quot;part1&quot;, 10, 10);
          Order secondOrder = new Order(&quot;part2&quot;, 20, 20);
          Company testCompany = companyRepository.save(new Company(&quot;TestCompany&quot;, parent, Set.of(firstChild, secondChild), Set.of(firstOrder, secondOrder)));
  
          var result = companyRepository.findById(testCompany.getId());
  </code></pre>
  <ul>
  <li>Expectation: cascade creation of all companies &amp; orders</li>
  <li>Reality: <code>org.springframework.data.mapping.MappingException: Error mapping Record&lt;{__sn__: node&lt;0&gt;, __sr__: [relationship&lt;0&gt;, relationship&lt;1&gt;, relationship&lt;2&gt;, relationship&lt;3&gt;, relationship&lt;4&gt;], __srn__: [node&lt;0&gt;, node&lt;1&gt;, node&lt;2&gt;, node&lt;3&gt;, node&lt;4&gt;, node&lt;5&gt;]}&gt;</code></li>
  </ul>
  <p>I have the assumption, that maybe it's not the <code>repo.save</code> issue, but <code>repo.findById()</code> issue, that' why I created the third test:</p>
  <pre><code>    @Test
      void basicPropertyUpdate() {
          //not sure if this initializatio work, because of the issue mentioned on test 1 &amp; 2
          Company parent = companyRepository.save(new Company(&quot;parent&quot;, null, null, null));
          Company firstChild = companyRepository.save(new Company(&quot;Child1&quot;, null, null, null));
          Company secondChild = companyRepository.save(new Company(&quot;Child2&quot;, null, null, null));
          Order firstOrder = orderRepository.save(new Order(&quot;part1&quot;, 10, 10));
          Order secondOrder = orderRepository.save(new Order(&quot;part2&quot;, 20, 20));
          Company testCompany = companyRepository.save(new Company(&quot;TestCompany&quot;, parent, Set.of(firstChild, secondChild), Set.of(firstOrder, secondOrder)));
  
          var companyToUpdate = companyRepository.findById(testCompany.getId()).orElseThrow();
          companyToUpdate.setName(&quot;NewName&quot;);
          var updatedCompany = companyRepository.save(companyToUpdate);
  </code></pre>
  <ul>
  <li>Expectation: will save only basic property</li>
  <li>Concern: if parent &amp; children aren't nulls, and that's the findById issue while performing basic property update also the relation to parent &amp; child will be overridden and will remove them.</li>
  </ul>
  <p>I didn't write the fourth test, but it is related to how we should update relations e.g. by adding or removing the <code>child</code> set, relations of relations are safe or still can be overridden because relation nodes of relation nodes can be also nulls?</p>
  <p>I have read all <a href="https://docs.spring.io/spring-data/neo4j/docs/6.1.5/reference/html/" rel="nofollow noreferrer">the documentation</a>, but it didn't give me a clear answer (I will say more, it caused more misunderstanding). I used <code>Spring Boot 2.5.5</code> with <code>spring-boot-starter-data-neo4j</code> (Spring data neo4j 6.1.5)</p>
  <p>I've given quite a bit of an introduction, but the question(s) seems relatively simple.</p>
  <ol>
  <li>Why am I not able to create the above-mentioned structure (with the <code>repository.save</code>)? Or why is findById unable to recreate it?</li>
  <li>How to correctly update basic property &amp; relation of the existing nodes (with the <code>repository.save</code>) without fear that something will be accidentally deleted?</li>
  </ol>