title: Spring Data JPA: Batch insert for nested entities
body: <p>I have a test case where I need to persist 100'000 entity instances into the database. The code I'm currently using does this, but it takes up to 40 seconds until all the data is persisted in the database. The data is read from a JSON file which is about 15 MB in size.</p>
  
  <p>Now I had already implemented a batch insert method in a custom repository before for another project. However, in that case I had a lot of top level entities to persist, with only a few nested entities.</p>
  
  <p>In my current case I have 5 <code>Job</code> entities that contain a List of about ~30 <code>JobDetail</code> entities. One <code>JobDetail</code> contains between 850 and 1100 <code>JobEnvelope</code> entities.</p>
  
  <p>When writing to the database I commit the List of <code>Job</code> entities with the default <code>save(Iterable&lt;Job&gt; jobs)</code> interface method. All nested entities have the CascadeType <code>PERSIST</code>. Each entity has it's own table.</p>
  
  <p>The usual way to enable batch inserts would be to implement a custom method like <code>saveBatch</code> that flushes every once in a while. But my problem in this case are the <code>JobEnvelope</code> entities. I don't persist them with a <code>JobEnvelope</code> repository, instead I let the repository of the <code>Job</code>entity handle it. I'm using MariaDB as database server.</p>
  
  <p>So my question boils down to the following: How can I make the <code>JobRepository</code> insert it's nested entities in batches?</p>
  
  <p>These are my 3 entites in question:</p>
  
  <h2>Job</h2>
  
  <pre><code>@Entity
  public class Job {
    @Id
    @GeneratedValue
    private int jobId;
  
    @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.PERSIST, mappedBy = "job")
    @JsonManagedReference
    private Collection&lt;JobDetail&gt; jobDetails;
  }
  </code></pre>
  
  <h2>JobDetail</h2>
  
  <pre><code>@Entity
  public class JobDetail {
    @Id
    @GeneratedValue
    private int jobDetailId;
  
    @ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.PERSIST)
    @JoinColumn(name = "jobId")
    @JsonBackReference
    private Job job;
  
    @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.PERSIST, mappedBy = "jobDetail")
    @JsonManagedReference
    private List&lt;JobEnvelope&gt; jobEnvelopes;
  }
  </code></pre>
  
  <h2>JobEnvelope</h2>
  
  <pre><code>@Entity
  public class JobEnvelope {
    @Id
    @GeneratedValue
    private int jobEnvelopeId;
  
    @ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.PERSIST)
    @JoinColumn(name = "jobDetailId")
    private JobDetail jobDetail;
  
    private double weight;
  }
  </code></pre>