1

How is a Hibernate EntityManager to be used in a multi thread application (eg each client connection starts it's own thread on the server).

Should EntityManager only created once by EntityManagerFactory, like:

private static EntityManagerFactory emf = Persistence.createEntityManagerFactory("unit");
private static EntityManager em = emf.createEntityManager();
    public static EntityManager get() {
        return em;
    }

Or do I have to recreate the entitymanger for every thread, and for every transaction that closes the EM?

My CRUD methods will look like this:

public void save(T entity) {
    em.getTransaction().begin();
    em.persist(entity);
    em.getTransaction().commit();
    em.close();
}

public void delete(T entity) {
    em.getTransaction().begin();
    em.remove(entity);
    em.getTransaction().commit();
    em.close();
}

Would I havew to run emf.createEntityManager() before each .begin()? Or am I then getting into trouble because each is creating an own EntityManager instance with it's own cache?

membersound
  • 66,525
  • 139
  • 452
  • 886
  • So with this, obviously I would have one single EMF, and create a new EM for every thread. But still: would I need to recreate the EM every time (multiple times during a thread) for every transaction, if I close the EM after each transaction? – membersound Jan 08 '14 at 14:23
  • After you close the EM you can't use it anymore. But you can of course use one EM for several transactions. Keep in mind that a EM is a lightweight object designed for cheap creation. Identify your units of work and use one EM for them. You might find the [reference documentation](http://docs.jboss.org/hibernate/entitymanager/3.6/reference/en/html/) interesting. – Markus Malkusch Jan 08 '14 at 14:41

1 Answers1

4

5.1. Entity manager and transaction scopes:

An EntityManager is an inexpensive, non-threadsafe object that should be used once, for a single business process, a single unit of work, and then discarded.

This answers perfectly your question. Don't share EMs over threads. Use one EM for several transactions as long as those transactions are part of a unit of work.

Furthermore you can't use an EntityManger after you've closed it:

After the close method has been invoked, all methods on the EntityManager instance and any Query, TypedQuery, and StoredProcedureQuery objects obtained from it will throw the IllegalStateException.

Consider something like this:

public class Controller {

    private EntityManagerFactory emf;

    public void doSomeUnitOfWork(int id) {
        EntityManager em = emf.createEntityManager();
        em.getTransaction().begin();

        CrudDao dao = new CrudDao(em);

        Entity entity = dao.get(id);
        entity.setName("James");
        dao.save(entity);

        em.getTransaction.commit();
        em.close();
    }

}
Markus Malkusch
  • 7,201
  • 35
  • 61
  • Yes since EM is not thread safe , can it be used across multiple threads if I create a wrapper around it and include 'synchronized' save/update methods in the wrapper which internally call save/update of EM. Also i never clear/close the EM ? I think there can still be issues for simultaneous read and write. Could you please let me know your comments on this ? – bluelurker May 06 '16 at 17:52
  • Why would you want to add such complexity while an EM is inexpensive to create? I can only imagine this makes sense if your threads share the same context in which the unit of work lives. – Markus Malkusch May 06 '16 at 18:06
  • Yes creating a separate EM for each thread is definitely the best option. I was just curious if what I said above is safe enough. Could you throw some light on the 'same context' part. I'm sorry I didn't get it. – bluelurker May 06 '16 at 18:15