为给定的PersistenceContext注入了多少个EntityManager?

时间:2012-11-17 16:41:32

标签: java jpa ejb-3.0

我在无状态 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

2 个答案:

答案 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/