title: Grails, Inserting lots of data using withTransaction results in OutOfMemoryError
body: <p>I'm using Grails 1.1 beta2. I need to import a large amount of data into my Grails application. If I repeatedly instantiate a grails domain class and then save it, the performance is unacceptably slow. Take for example importing people from a phone book:</p>
  
  <pre><code>for (each person in legacy phone book) {
      // Construct new Grails domain class from legacy phone book person
      Person person = new Person(...)
      person.save()
  }
  </code></pre>
  
  <p>This turns out be painfully slow. Someone on the Grails mailing list suggest batching up saves in a transaction. So now I have:</p>
  
  <pre><code>List batch = new ArrayList()
  for (each person in legacy phone book) {
      // Construct new Grails domain class from legacy phone book person
      Person person = new Person(...)
      batch.add(person)
      if (batch.size() &gt; 500) {
          Person.withTransaction {
              for (Person p: batch)
                  p.save()
              batch.clear()
          }
      }
  }
  // Save any remaining
  for (Person p: batch)
      p.save()
  </code></pre>
  
  <p>This works must faster, at least initially. Each transaction saves 500 records. As time goes on, the transactions take longer and longer. The first few transactions takes about 5 seconds, then it just creeps from there. After about 100 transactions, each one takes over a minute, which is once again unacceptable. Worse is that eventually Grails will eventually run out of Java heap memory. I can increase the JVM heap size, but that just delays the <code>OutOfMemoryError</code> exception.</p>
  
  <p>Any ideas why this is? It's like there some internal resource not being released. The performance gets worse, memory is being held on to, and then eventually the system runs out of memory.</p>
  
  <p>According to the <a href="http://grails.org/doc/1.0.x/ref/Domain%20Classes/withTransaction.html" rel="noreferrer">Grails documentation</a>, <code>withTransaction</code> passes the closure to Spring's <code>TransactionStatus</code> object. I couldn't find anything in <code>TransactionStatus</code> to close/end the transaction.</p>
  
  <p><strong>Edit:</strong> I'm running this from Grails' Console (<code>grails console</code>)</p>
  
  <p><strong>Edit:</strong> Here's the out of memory exception:</p>
  
  <pre><code>Exception thrown: Java heap space
  
  java.lang.OutOfMemoryError: Java heap space
      at org.hibernate.util.IdentityMap.entryArray(IdentityMap.java:194)
      at org.hibernate.util.IdentityMap.concurrentEntries(IdentityMap.java:59)
      at org.hibernate.event.def.AbstractFlushingEventListener.prepareEntityFlushes(AbstractFlushingEventListener.java:113)
      at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:65)
      at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:26)
      at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
      at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:338)
      at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106)
      at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:655)
      at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:732)
      at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:701)
      at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140)
  </code></pre>