Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Running multiple JPA transactions in parallel

I have two (or more) Java Threads creating, updating and deleting entities from a mysql database using JPA. To achieve this I have a PersistenceLayer class creating the EntityManager and providing save, update and delete methods for all my entities looking like:

public void saveEntity(Entity entity) {
    manager.getTransaction().begin();
    manager.persist(entity);
    manager.getTransaction().commit();
}

public void saveEntity2(Entity2 entity) {
    manager.getTransaction().begin();
    manager.persist(entity);
    manager.getTransaction().commit();
}

If one thread enters operation saveEntity and the other saveEntity2 at the same time, both will try to get the transaction from the EntityManager wich will fail. However I always thought that the underlying database is able to manage multiple transactions, especially if both are working on different rows or even different tables. Of course I could synchronize the blocks, but that would mean only one DB connection is possible at a time which will not scale to multiple users creating several threads.

What wrong assumption am I doing here? Is it possible to submit multiple transactions to a database via JPA and let the DB handle concurrency issues?

like image 864
ali Avatar asked May 11 '11 15:05

ali


2 Answers

EntityManager is not intended to be used by multiple threads. You need to obtain separate instances of EntityManager for each thread.

Actually, if you use EJB or Spring you can use a transaction-scoped EntityManager, which can be used from multiple threads (it's a proxy which delegates actual work to separate thread-bound instances of EntityManager), but I think it's not your case.

like image 153
axtavt Avatar answered Sep 22 '22 23:09

axtavt


To handle concurrency issues when the object is being processed accross multiple transactions, lock can be acquired on the object. Either Optimistic or Pessimistic locking can be used with appropriate lock-modes.

Locking the versioned object by entityManager.lock(entity, LockModeType.READ) will ensure that it will prevent any Dirty Read & Non-Repeatable Read.

LockModeType.WRITE will force incrementing/updating the version column of the entity.

like image 44
Nayan Wadekar Avatar answered Sep 24 '22 23:09

Nayan Wadekar