JPA EntityManager Static or Instance?

PhilippeLM picture PhilippeLM · Dec 23, 2011 · Viewed 11.7k times · Source

I've built some JPA stuff in the past that used an instance of the javax.persistence.EntityManager per instance of DAO; this is the way most examples are setup.

public class BaseDaoThatEveryDaoExtends {
   @PersistenceContext
   private EntityManager entityManager;
}

I've just stumbled upon code that uses a static javax.peristence.EntityManger injected by a PersistenceContext annotation, the architect tells me this causes no problems and they never had any problem even in a clustered application with JTA and an XA data source:

public class BaseDaoThatEveryDaoExtends {
   @PersistenceContext
   private static EntityManager entityManager;
}

As far as I can tell this is an anti-pattern as the EntityManager holds some state information and making it static makes that whole state application wide. Also this makes the classes very hard to test.

Are there other drawbacks to doing this or is this a standard way of using an EntityManager ?

Answer

Edwin Dalorzo picture Edwin Dalorzo · Dec 24, 2011

I think the major risk is not in the EntityManager itself, but in the application context that is attached to the entity manager when it is used.

Let's assume you have two different clients making a request to your server, both invoking two different methods of your application, both running on different threads, but both using the same entity manager.

As far as I know the entity manager will have a single context attached to it, this context will be shared by both clients. Every time you load an instance to the context, will be available to threads through the shared entity manager. What will happen if they tamper with each other's data? What will happen if they are using different transaction isolation configuration?. How can you possibly be sure that client 1 is not altering data being currently used by client 2?

What if one of the clients invalidates the context, what will the other do? How do you deal with concurrency this way?