4

我在无状态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(例如AFacadeBFacade等)都注入了不同的EntityManager(由identityHashCode报告),尽管PersistenceContext是相同的。在所有情况下,实现类都是TransactionScopedEntityManager 。

我不清楚为什么要注入这些不同的EntityManager对象,这是否应该让我担心。另外,我知道 EJB3 容器实际上可能会向真实的EntityManager注入代理,因此这些不同的实例实际上可能是单个EntityManager的代理。

4

2 回答 2

4

是的,它们是真实实体管理器的代理(实际上,我认为它们是线程安全的装饰器,而不是代理)。

我不确定您是否知道 EntityManager 是连接的包装器。如果您没有此装饰器(或代理),则对该无状态 bean 的所有调用将共享相同的连接(并且可能是事务),这不是您想要的。

于 2012-11-17T16:44:28.973 回答
4

注入的 EntityManager 是由 EJB 容器生成的代理。

对于事务范围的实体管理器,每个事务使用一个单独提供者实体管理器实例。

当对此代理进行方法调用时,容器会检查javax.transaction.TransactionSynchronizationRegistry(这由 EJB 容器实现)以查看是否已经为此事务创建了提供者 EntityManager。如果没有,它将创建提供者实体管理器并将其注册到 TransactionSynchronizationRegistry 中,然后将方法调用委托给它。如果已经存在,它将简单地检索提供者实体管理器,并将方法调用委托给它。

根据 Mike Keith 和 Merrick Schincariol 所著的“Pro JPA2 Mastering the Java Persistence API”一书(参见第 6 章),事务范围的 EntityManager 是无状态的。

插入到每个 EJB 实例对象中的代理对象是不同的,尽管由于事务范围实体管理器的无状态特性,可以使用单个代理对象。

也看看: http: //piotrnowicki.com/2011/11/am-i-in-the-same-transaction-am-i-using-the-same-persistencecontext/

于 2012-12-09T06:14:15.230 回答