我在无状态 EJB3 bean中注入 EntityManager 对象(充当 DAO 对象,并且每个对象提供对不同数据库表的访问权限)。部署在 JBoss AS 7 。
然后我在 EJB3 bean方法中使用 System.identityHashCode 添加代码,以查看 EntityManagers 注入的各种实例(希望看到所有DAO中的相同实例)。例如。像:
@Stateless
public class AFacade {
@PersistenceContext(unitName="foo")
EntityManager em;
public List<A> findAll() {
l.info("entity manager is: "+System.identityHashCode(em)+" class is: "+em.getClass().getSimpleName());
...
}
然而,我注意到每个 DAO (例如 AFacade , BFacade 等)注入了不同的 EntityManager (由 identityHashCode 报告)虽然 PersistenceContext 是相同的。在所有情况下,实现类都是 TransactionScopedEntityManager 。
我不清楚为什么会注入这个不同的 EntityManager 对象,这是否与我有关。另外,据我所知,EJB3容器实际上可以将代理注入真实的 EntityManager ,因此这些不同的实例实际上可能代理单个 EntityManager 。
答案 0 :(得分:4)
是的,它们是代理(实际上,我认为它们是真正的实体管理器上的线程安全装饰器,而不是代理)。
我不确定您是否知道EntityManager是连接的包装器。如果您没有这个装饰器(或代理),那么对该无状态bean的所有调用都将共享相同的连接(以及可能的事务),这不是您想要的。
答案 1 :(得分:4)
注入的EntityManagers是EJB容器生成的代理。
对于 事务范围的实体经理 ,每个事务都使用 提供商的实体管理器的单独实例 强>
当对此代理进行方法调用时,容器会检查 javax.transaction.TransactionSynchronizationRegistry (这是由EJB容器实现的)以查看是否存在提供程序EntityManager已为此交易创建。如果没有,它将创建提供者实体管理器并在TransactionSynchronizationRegistry中注册它,然后将方法调用委托给它。如果已经存在,它将只是检索提供者实体管理器一个委托方法调用它。
根据Mike Keith和Merrick Schincariol撰写的“Pro JPA2掌握Java持久性API”一书,事务范围EntityManagers是无状态的 (参见第6章)。
插入每个EJB实例对象中的代理对象是不同的,但由于事务范围实体管理器的无状态特性,可能已使用单个代理对象。
另请查看:http://piotrnowicki.com/2011/11/am-i-in-the-same-transaction-am-i-using-the-same-persistencecontext/