Search code examples
javajpaentitymanagerconcept

Handle multiple EntityManager in Java EE application


I have Java EE application with about 10 EntityManagers (number of EMs will probably increase). My application also contains many stateless, statefull and message driven beans.

Rather than inject in each bean my EMs with @PersistenceContext (and 2 methods to detect which EM to use for user), I probably store all of that inside a singleton bean and access it with others beans. Like that, no worries about maintainability.

Nevertheless, is it thread-safe to store EMs inside one singleton bean? Can a bottleneck appear?

Another solution is to create an abstract class and all beans will extend it.

What is the better solution?


Solution

  • Container managed entity managers are automatically propagated with the current JTA transaction and EntityManager references that are mapped to the same persistence unit provide access to the persistence context within that transaction. So it's not good practice to share an entity manager from a singleton, apart from concurrency problems, it would result in using the same transaction context for every method you call on your beans.
    A simple solution to your need is to inject EntityManagerFactory references in your beans and create EntityManager objects calling the createEntityManager() method. The drawback is that you should manage transactions manually, no more relying on the container.
    Otherwise another approach could be inject all of your entity managers in a main enterprise bean and implement business logic in service beans with methods to which you pass the appropriate managers. An example of the latter solution:

    @Stateless
    class MainBean {
        @PersistenceContext EntityManager em1;
        @PersistenceContext EntityManager em2;
        ...
        @EJB WorkerBean1 workerBean1;
        @EJB WorkerBean2 workerBean2;
        ...
        void method1(Object param1, Object param2) {
            workerBean1.method1(em1, param1, param2);
        }
    
        void method2(Object param1, Object param2, Object param3) {
            workerBean2.method2(em2, param1, param2, param3);
        }
        ...
    }
    
    @Stateless
    class WorkerBean1 {
        void method1(EntityManager em, Object param1, Object param2) {
            ...
        }
        ...
    }
    
    @Stateless
    class WorkerBean2 {
        void method2(EntityManager em, Object param1, Object param2, Object param3) {
            ...
        }
        ...
    }