tags:

views:

1113

answers:

1

Hi,

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?

+2  A: 

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.

cletus
Thanks for the reply. Within my Dao method would it help then to use Persist() instead of Merge() since they are new entities?
Lancelot
merge() and persist() have different semantics. It's not a simple issue and I'd strongly suggest some reading about JPA.
cletus