Handle multiple EntityManager in Java EE application

后端 未结 3 930
夕颜
夕颜 2020-12-19 10:29

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 bea

3条回答
  •  情歌与酒
    2020-12-19 11:33

    An entity manager is not supposed to be thread-safe, so you shouldn't share ones via a Singleton. It's the same reason as why you should not inject an entity manager into a Servlet, and why a lookup from JNDI in such a web component -should- return a different instance of the entity manager ever time.

    In practice some implementations may provide an entity manager that is thread-safe, so during testing it may seem to work. However, for the sake of portability and to protect you against upgrade woes, you should never rely on this.

    Instead of inheriting from a common base class, you could define all your entity managers in one bean, and inject that wherever you need an entity manager.

    E.g.

    @Stateless
    public class EntityManagerProviderBean {
    
        @PersistenceContext(unitName="foo")
        private EntityManager entityManagerFoo;
    
        @PersistenceContext(unitName="bar")
        private EntityManager entityManagerBar;
    
        public EntityManager getEntityManager() {
            return ...? entityManagerFoo : entityManagerBar;
        }
    }
    

    (where ... is the logic you use to select the right entity manager)

    Inject this into a bean needing an entity manager:

    @Stateless
    public class MyService {
    
        @EJB
        private EntityManagerProviderBean entityManagerProvider;
    
        public void doStuff(MyEntity myEntity) {
            entityManagerProvider.getEntityManager().update(myEntity);
        }
    
    }
    

    Alternatively the following would perhaps be even neater:

    @Stateless
    @PersistenceContexts({ 
        @PersistenceContext(unitName="foo", name = "fooENC"),
        @PersistenceContext(unitName="bar", name = "barENC") }
    )
    public class EntityManagerProviderBean {
    
        @Resource
        private EJBContext context;
    
        public EntityManager getEntityManager() {
            return (EntityManager) context.lookup(... ? "fooENC" : "barENC");
        }
    }
    

    The last example maps all persistence contexts into the ENC of the bean, where they can be conveniently retrieved programmatically.

    Unfortunately, people forgot to add tests for the latter syntax to the TCK and subsequently major vendors forgot to implement it (see http://java.net/jira/browse/JPA_SPEC-38 and https://issues.jboss.org/browse/AS7-5549), so test if this works on your server.

提交回复
热议问题