Search code examples
jpainsertbulk

Portable JPA Batch / Bulk Insert


I just jumped on a feature written by someone else that seems slightly inefficient, but my knowledge of JPA isn't that good to find a portable solution that's not Hibernate specific.

In a nutshell the Dao method called within a loop to insert each one of the new entities does a "entityManager.merge(object);".

Isnt' there a way defined in the JPA specs to pass a list of entities to the Dao method and do a bulk / batch insert instead of calling merge for every single object?

Plus since the Dao method is annotated w/ "@Transactional" I'm wondering if every single merge call is happening within its own transaction... which would not help performance.

Any idea?


Solution

  • No there is no batch insert operation in vanilla JPA.

    Yes, each insert will be done within its own transaction. The @Transactional attribute (with no qualifiers) means a propagation level of REQUIRED (create a transaction if it doesn't exist already). Assuming you have:

    public class Dao {
      @Transactional
      public void insert(SomeEntity entity) {
        ...
      }
    }
    

    you do this:

    public class Batch {
      private Dao dao;
    
      @Transactional
      public void insert(List<SomeEntity> entities) {
        for (SomeEntity entity : entities) {
          dao.insert(entity);
        }
      }
    
      public void setDao(Dao dao) {
        this.dao = dao;
      }
    }
    

    That way the entire group of inserts gets wrapped in a single transaction. If you're talking about a very large number of inserts you may want to split it into groups of 1000, 10000 or whatever works as a sufficiently large uncommitted transaction may starve the database of resources and possibly fail due to size alone.

    Note: @Transactional is a Spring annotation. See Transactional Management from the Spring Reference.