title: Delete then create records are causing a duplicate key violation with Spring Data JPA
body: <p>So, I have this scenario where I need to take a header record, delete the details for it, then re-create the details in a different way.  Updating the details would be way too much trouble.</p>
  
  <p>I basically have:</p>
  
  <pre><code>@Transactional
  public void create(Integer id, List&lt;Integer&gt; customerIDs) {
  
      Header header = headerService.findOne(id);
      // header is found, has multiple details
  
      // Remove the details
      for(Detail detail : header.getDetails()) {
          header.getDetails().remove(detail);
      }
  
      // Iterate through list of ID's and create Detail with other objects
      for(Integer id : customerIDs) {
          Customer customer = customerService.findOne(id);
  
          Detail detail = new Detail();
          detail.setCustomer(customer);
  
          header.getDetails().add(detail);
      }
  
      headerService.save(header);
  }
  </code></pre>
  
  <p>Now, the database has a constraint like the following:</p>
  
  <pre><code>Header
  =================================
  ID, other columns...
  
  Detail
  =================================
  ID, HEADER_ID, CUSTOMER_ID
  
  Customer
  =================================
  ID, other columns...
  
  Constraint:  Details must be unique by HEADER_ID and CUSTOMER_ID so:
  
  Detail  (VALID)
  =================================
  1, 123, 10
  2, 123, 12
  
  Detail  (IN-VALID)
  =================================
  1, 123, 10
  1, 123, 10
  </code></pre>
  
  <p>OK, when I run this and pass in 2, 3, 20, etc. customers, it creates all <code>Detail</code> records just fine as long as there weren't any before.</p>
  
  <p>If I run it again, passing in a different list of customers, I expect <code>ALL</code> details to be deleted first then a list of <code>NEW</code> details to be created.</p>
  
  <p>But what's happening is that the delete doesn't seem to be honored before the create.  Because the error is a duplicate key constraint.  The duplicate key is the "IN-VALID" scenario above.</p>
  
  <p>If I manually populate the database with a bunch of details and comment out the <code>CREATE details</code> part (only run the delete) then the records are deleted just fine.  So the delete works.  The create works.  It's just that both don't work together.</p>
  
  <p>I can provide more code is needed.  I'm using <code>Spring Data JPA</code>.</p>
  
  <p>Thanks</p>
  
  <p><strong>UPDATE</strong></p>
  
  <p>My entities are annotated with basically the following:</p>
  
  <pre><code>@Entity
  @Table
  public class Header {
  ...
      @OneToMany(mappedBy = "header", orphanRemoval = true, cascade = {CascadeType.ALL}, fetch = FetchType.EAGER)
      private Set&lt;Detail&gt; Details = new HashSet&lt;&gt;();
  
  ...
  }
  
  @Entity
  @Table
  public class Detail {
  ...
      @ManyToOne(optional = false)
      @JoinColumn(name = "HEADER_ID", referencedColumnName = "ID", nullable = false)
      private Header header;
  ...
  }
  </code></pre>
  
  <p><strong>UPDATE 2</strong></p>
  
  <p>@Klaus Groenbaek</p>
  
  <p>Actually, I didn't mention this originally but I did it that way the first time.  Also, I am using Cascading.ALL which I assume includes PERSIST.</p>
  
  <p>Just for testing, I have updated my code to the following:</p>
  
  <pre><code>@Transactional
  public void create(Integer id, List&lt;Integer&gt; customerIDs) {
  
      Header header = headerService.findOne(id);
  
      // Remove the details
      detailRepository.delete(header.getDetails());       // Does not work
  
      // I've also tried this:
      for(Detail detail : header.getDetails()) {
          detailRepository.delete(detail);
      }
  
  
      // Iterate through list of ID's and create Detail with other objects
      for(Integer id : customerIDs) {
          Customer customer = customerService.findOne(id);
  
          Detail detail = new Detail();
          detail.setCustomer(customer);
          detail.setHeader(header);
  
          detailRepository.save(detail)
      }
  }
  </code></pre>
  
  <p>Again...I want to reiterate....that the delete WILL WORK if I don't have the create immediately afterwards.   The create WILL WORK if I don't have the delete immediately before it.  But neither will work if they are together because of the duplicate key constraint error from the database.</p>
  
  <p>I've tried the same scenario WITH and WITHOUT cascading deletes.</p>