Thread-safety when injecting JPA EntityManager

Thread-safety when injecting JPA EntityManager

Injecting  EJB 3  stateful beans into servlet instance fields is not thread-safe. Along the same line, injecting  EntityManager  with  @PersistenceContext  into servlet instance variables is not thread-safe, either.  EntityManager  is just not designed to be thread-safe.

For example, the following code snippet of a servlet class is incorrect:

?
1
2
3
4
5
6
7
public class EMTestServlet extends HttpServlet {
   //This field injection is not thread-safe.
   //FIXME
   @PersistenceContext
   private EntityManager em;
...
}

One way to fix this is to inject  EntityManagerFactory  instead.  EntityManagerFactory  is guaranteed to be  thread-safe . For example:
?
1
2
3
4
5
6
7
8
9
10
11
12
public class EMTestServlet extends HttpServlet {
   //This field injection is thread-safe
   @PersistenceUnit
   private EntityManagerFactory emf;
  
   protected void doGet(HttpServletRequest request,
              HttpServletResponse response)
   throws ServletException, IOException {
   EntityManager em = emf.createEntityManager();
   //work with em
   }
}

Continuing container-managed EntityManager vs application-managed EntityManager.

There are important differences between the injected  EntityManager , and the  EntityManager  created from an injected  EntityManagerFactory . Basically, injected  EntityManager  is container-managed, meaning all of its lifecycle is controlled by the container (web container or EJB container). Application code cannot close it, or otherwise interfere with its life.

In addition, for a container-managed  EntityManager , its associated  PersistenceContext  is automatically propagated along with the underlying JTA, from servlet A to servlet B, from servlet to EJB, from EJB a to EJB B, and so on. As such,  EntityManager  of the same configuration injected into various classes can share the same  PersistenceContext  in a call stack.

On the other hand,  EntityManager  created from  EntityManagerFactory  is application-managed  EntityManager . Application code is responsible for managing its whole lifecycle. And there is no  PersistenceContext  propagation for application-managed  EntityManager .

Are all  EntityManager's  obtained from  EntityManagerFactory  application-managed  EntityManager Yes.

Is it possible to get a container-managed  EntityManager  from  EntityManagerFactory No.

You may have read about the method  EntityManagerFactory.getEntityManager() , which returns a container-managed  EntityManager . This method was considered and included in the early draft version of Java Persistence API, but was eventually removed from its final release.

你可能感兴趣的:(Thread-safety when injecting JPA EntityManager)