title: JPA persist becomes slower and slower
body: <p>This scenario uses a simple oneToMany relationship with cascade persist on both directions.</p>
  
  <p><strong>Many:</strong></p>
  
  <pre><code>@javax.persistence.Entity(name="Many")
  public class Many {
      @javax.persistence.ManyToOne(cascade = CascadeType.PERSIST)
      protected One one;
  
      @Id
      @GeneratedValue(strategy = GenerationType.IDENTITY)
      private long primaryKey;
  
      public void setM(One one) {
          this.one = one;
          // comment out this line and performance becomes stable
          this.one.getMany().add(this);
      }
  
      // other setters, getters, etc...
  }
  </code></pre>
  
  <p><strong>One:</strong></p>
  
  <pre><code>@javax.persistence.Entity(name="One")
  public class One {
      @javax.persistence.OneToMany(mappedBy="m", cascade = CascadeType.PERSIST)
      protected java.util.Set&lt;Many&gt; many = com.google.common.collect.Sets.newHashSet();
  
      @Id
      @GeneratedValue(strategy = GenerationType.IDENTITY)
      private long primaryKey;
  
      private String name;
  
      // setters, getters, etc... 
  }
  </code></pre>
  
  <p><strong>Test:</strong></p>
  
  <pre><code>public static void main(String[] args) {
      while(true) {
          EntityManagerFactory emf = Persistence.createEntityManagerFactory("test-pu");
          EntityManager em = emf.createEntityManager();
  
          for (int i = 0; i &lt; 100; i++) {
              sw.reset();
              sw.start();
              persistMVs(emf, em);
              System.err.println("Elapsed: " + sw.elapsed(TimeUnit.MILLISECONDS) + " ms");
          }
  
          em.close();
          emf.close();
      }
  }
  
  private static void persistMVs(EntityManagerFactory emf, EntityManager em) {
      em.getTransaction().begin();
      One one = getOrCreateOne(em);
  
      for (int i = 0; i &lt; 200; i++) {
          Many many = new Many();
          many.setM(one);
          em.persist(many);
      }
      em.getTransaction().commit();
  }
  </code></pre>
  
  <p>The test is an endless loop which tries to insert 20000 <code>Many</code> entities associated with a single <code>One</code> entity. Each loop begins with the creation of a new <code>EntityManagerFactory</code> to show the negative performance effect of the increasing database.</p>
  
  <p>The expected behavior would be that, the insertion time of the entities does not increase drastically, however after each <strong>WHILE CYCLE</strong> there is an order of magnitude increase.</p>
  
  <p><strong>Notes:</strong></p>
  
  <ul>
  <li>I have tried eclipseLink, Hibernate, OpenJPA and all suffered from this kind of slowdown. </li>
  <li>If I don't update the Many collection of One, then there is no degradation (see the commented line of Many).</li>
  <li><strong>If I don't create a new EntityManagerFactory, then there is no degradation even after half a million entities.</strong></li>
  <li>The slow part is <code>em.persist(many);</code> (I measured it).</li>
  <li>Check out <a href="https://github.com/kupsef/OneToMany" rel="nofollow">https://github.com/kupsef/OneToMany</a> and start the test with
  <code>gradle start</code>.</li>
  </ul>
  
  <p>Why would the initial size of the database matter in this case? Should I consider this behavior as a bug?</p>