Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JAVA: an EntityManager object in a multithread environment

Tags:

if I have multiple threads, each use injector to get the EntityManager object, each use the em object to select a list of other class objects. Ready to be used in a for loop.

If a thread finishes first and calls clear(), will that affect the other threads? Like the for loop will have exception?

How about close()?

If the answer is "It depends", what (class definition? method call?) and where (java code? annotation? xml?) should I look at to find out how is it depended?

I did not write the source, I am just using someone else's library without documentation.

Thank you.

like image 856
user1589188 Avatar asked Feb 15 '13 03:02

user1589188


People also ask

Is the JPA EntityManager object thread safe?

No, an EntityManager is NOT thread safe.

Is EntityManagerFactory and EntityManager thread safe?

EntityManagerFactory instances are thread-safe. Applications create EntityManager instances in this case by using the createEntityManager method of javax.

What is difference between EntityManagerFactory and EntityManager?

EntityManagerFactory vs EntityManager EntityManager: whenever using spring avoid managing/using EntityManagerFactory since Spring manages concurreny for you. The entity manger injected by @PersistenceContext is thread safe. While EntityManagerFactory instances are thread-safe, EntityManager instances are not.

Does EntityManager need to be closed?

If you don't close it your entities will be kept as attached, even after you're done using them. Your context will be kept alive even when you can no longer access your EM. The JPA Specification contains more details.


2 Answers

Here is full working thread-safe Entity Manager Helper.

import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence;  public class EntityManagerHelper {      private static final EntityManagerFactory emf;     private static final ThreadLocal<EntityManager> threadLocal;      static {         emf = Persistence.createEntityManagerFactory("Persistent_Name");         threadLocal = new ThreadLocal<EntityManager>();     }      public static EntityManager getEntityManager() {         EntityManager em = threadLocal.get();          if (em == null) {             em = emf.createEntityManager();             // set your flush mode here             threadLocal.set(em);         }         return em;     }      public static void closeEntityManager() {         EntityManager em = threadLocal.get();         if (em != null) {             em.close();             threadLocal.set(null);         }     }      public static void closeEntityManagerFactory() {         emf.close();     }      public static void beginTransaction() {         getEntityManager().getTransaction().begin();     }      public static void rollback() {         getEntityManager().getTransaction().rollback();     }      public static void commit() {         getEntityManager().getTransaction().commit();     } } 
like image 75
Makky Avatar answered Oct 10 '22 18:10

Makky


Entity managers are not thread-safe (source Java EE 6 tutorial) and cannot be shared among threads. Each thread needs to use its own entity manager or bad things will happen, regardless of clear() or close() calls.

But, if the injector is injecting each thread with its own entity manager then things should be OK.

Spring and possibly other DI frameworks will inject a ThreadLocal-based proxy for a real entity manager into your beans. Calls that each thread makes will proxy to the real thread-local instance of an entity manager - this is how things can work even though it might appear an entity manager is shared among multiple threads.

More details about how your entity manager is injected would help (Spring, etc.)

like image 23
prunge Avatar answered Oct 10 '22 16:10

prunge