我在这里谈论基本用法:

@Stateless
public class BookServiceBean implements BookService {
  @PersistenceContext EntityManager em;
  public void create(Book book) { this.em.persist(book);}
}

谷歌搜索上面的问题,StackOverflow说yes, but no-可接受的答案是"is",但是后续的回答是“否”。 Spring.io说both yes and no,似乎是Java EE专家的Adam Bien给出了unqualified yes

我自己对一个简单的调度bean的经验表明答案是否定的:
@Stateless
public class TimerTick implements TimerTickAbs, Runnable {
  @PersistenceContext private EntityManager entityManager;
  @Override
  public void run() {
    Query q = entityManager.createQuery("SELECT blah...");
  }
  @Override
  public Runnable runner() {
    return this;
  }
}

抽象界面:
@Local
public interface TimerTickAbs {
  public Runnable runner();
}

开始于:
@Resource ManagedScheduledExecutorService managedExecutorService;
@EJB TimerTick myRunner;

public void startup()
{
    managedExecutorService.scheduleAtFixedRate(myRunner.runner(), 3, 40, TimeUnit.SECONDS);
}

如果我打印出Thread.currentThread().getId(),即使我在两次调用之间仍处在同一线程上,我也会得到:



我知道我可以做类似@PersistenceUnit private EntityManagerFactory emf;的代码并自己管理EntityManager,但是我想利用@PersistenceContext给我的所有自动交易功能。

最佳答案

不,EntityManager不是线程安全的。亚当·比恩(Adam Bien)也是正确的。您只是没有正确地看问题。他要回答的问题不是EntityManager是否是线程安全的,而是要说明在无状态 session Bean中使用容器管理的EntityManger是安全的。然后,他解释了允许容器发挥其魔力的规范的理由和措辞-“每个实例仅看到序列化的方法调用序列”。这允许容器注入(inject)在每个方法调用中具有不同的EntityManager上下文,类似于每个调用可以如何绑定(bind)到其自己的事务和隔离的资源上。

注入(inject)实际上只是注入(inject)EntityManager代理,该代理使容器可以控制下面的JPA EntityManager的生命周期,从而使其能够与线程和事务绑定(bind)。

因此,EntityManager不是线程安全的,但是要求容器注入(inject)的EntityManager代理在无状态 session Bean中安全使用。

关于java - EntityManager真的是线程安全的吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/24643863/

10-12 05:08