Spring Data JPA: Batch insert for nested entities
<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>