尽管EntityManager实现本身不是线程安全的,但是Java EE容器注入了一个代理,该代理将所有方法调用委托给与事务绑定的EntityManager。因此,每个事务都使用其自己的EntityManager实例。至少对于事务范围的持久性上下文而言,这是正确的(默认设置)。
如果容器将在每个bean中注入EntityManager的新实例,则以下操作将无效:
@Statelesspublic class Repository1 { @EJB private Repository2 rep2; @PersistenceContext(unitName="blah", type = PersistenceContextType.TRANSACTION) private EntityManager em; @TransactionAttribute public void doSomething() { // Do something with em rep2.doSomethingAgainInTheSameTransaction(); }}@Statelesspublic class Repository2 { @PersistenceContext(unitName="blah", type = PersistenceContextType.TRANSACTION) private EntityManager em; @TransactionAttribute public void doSomethingAgainInTheSameTransaction() { // Do something with em }}doSomething-> doSomethingAgainInTheSameTransaction调用在单个事务中发生,因此bean必须共享相同的EntityManager。实际上,它们共享同一个代理EntityManager,该代理将调用委派给同一持久性上下文。
因此,您可以在单例bean 中合法使用EntityManager,如下所示:
@Singleton@ConcurrencyManagement(ConcurrencyManagementType.BEAN)public class Repository { @PersistenceContext(unitName="blah", type = PersistenceContextType.TRANSACTION) private EntityManager em;}另一个证明是,在EntityManager javadoc中没有提及线程安全。因此,当您停留在Java EE容器中时,无需关心对EntityManager的并发访问。



