Java CDI @PersistenceContext和线程安全

问题描述:

在多个类threadsafe中,EntityManager @Inject [ed]如下所示?

Is an EntityManager @Inject[ed] as follows in muliple classes threadsafe?

@PersistenceContext(unitName="blah")
private EntityManager em;

这个问题和这一个似乎是针对Spring的。我正在使用Jave EE CDI服务

This question and this one seem to be Spring specific. I am using Jave EE CDI services

虽然 EntityManager 实现本身不是线程安全的 Java EE 容器注入一个代理,该代理将所有方法调用委托给绑定了 EntityManager 的事务。因此,每个事务都使用它自己的 EntityManager 实例。这至少适用于事务范围的持久化上下文(默认情况下)。

Although EntityManager implementations itself are not thread safe the Java EE container injects a proxy which delegates all methods invocations to a transaction bound EntityManager. Therefore each transaction works with it's own EntityManager instance. This is true for at least transaction-scoped persistence context (which is default).

如果容器会在每个中注入一个新的 EntityManager 实例下面的bean不起作用:

If container would inject a new instance of EntityManager in each bean the below wouldn't work:

@Stateless
public 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();
   }
}

@Stateless
public class Repository2 {
   @PersistenceContext(unitName="blah", type = PersistenceContextType.TRANSACTION)
   private EntityManager em;

   @TransactionAttribute
   public void doSomethingAgainInTheSameTransaction() {
      // Do something with em
   }
}

doSomething-> doSomethingAgainInTheSameTransaction 调用在单个事务中发生,因此bean必须共享相同的 EntityManager 。实际上它们共享相同的代理 EntityManager ,它将调用委托给相同的持久化上下文。

doSomething->doSomethingAgainInTheSameTransaction call happens in a single transaction and therefore the beans must share the same EntityManager. Actually they share the same proxy EntityManager which delegates calls to the same persistence context.

所以你合法使用 EntityManager 在下面的单例bean中:

So you are legal use EntityManager in singleton beans like below:

@Singleton
@ConcurrencyManagement(ConcurrencyManagementType.BEAN)
public class Repository {
   @PersistenceContext(unitName="blah", type = PersistenceContextType.TRANSACTION)
   private EntityManager em;
}

另一个证明是中没有提及线程安全性EntityManager javadoc。因此,当您留在 Java EE 容器中时,您不应该关心对 EntityManager 的并发访问。

Another proof is that there is no any mention of thread safety in EntityManager javadoc. So while you stay inside Java EE container you shouldn't care about concurrency access to EntityManager.