EntityManager真的是线程安全的吗?

Ken*_*Y-N 7 java multithreading jpa glassfish-4

我在说这里的基本用法:

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

谷歌上面的问题,StackOverflow说是的,但没有 - 接受的答案是肯定的,但后续的是否定的; Spring.io说是和不,而且似乎是Java EE专家的Adam Bien给出了一个不合格的是.

我对一个简单的预定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;
  }
}
Run Code Online (Sandbox Code Playgroud)

抽象界面:

@Local
public interface TimerTickAbs {
  public Runnable runner();
}
Run Code Online (Sandbox Code Playgroud)

开始于:

@Resource ManagedScheduledExecutorService managedExecutorService;
@EJB TimerTick myRunner;

public void startup()
{
    managedExecutorService.scheduleAtFixedRate(myRunner.runner(), 3, 40, TimeUnit.SECONDS);
}
Run Code Online (Sandbox Code Playgroud)

如果我打印出来Thread.currentThread().getId(),即使我仍然在通话之间的同一个线程,我得到:

SEVERE:java.lang.IllegalStateException:尝试在已关闭的EntityManager上执行操作

我知道我可以自己做代码@PersistenceUnit private EntityManagerFactory emf;并管理EntityManager自己,但我想利用@PersistenceContext给我的所有自动交易内容.

Chr*_*ris 11

不,EntityManager不是线程安全的.Adam Bien虽然也是正确的.你只是没有正确地看待这个问题.他回答的问题不是如果EntityManager是线程安全的,他说明在无状态会话bean中使用容器管理的EntityManger是安全的,它就是这样.然后他解释了允许容器发挥其魔力的规范的推理和措辞 - "每个实例只能看到序列化的方法调用序列".这允许容器注入每个方法调用具有不同的EntityManager上下文,类似于每个调用如何绑定到它们自己的事务和隔离的资源.

注入实际上只是注入一个EntityManager代理,它允许容器控制下面的JPA EntityManagers的生命周期,允许它绑定到线程和事务.

因此,EntityManager不是线程安全的,但注入EntityManager代理的容器必须在无状态会话bean中安全使用.


yas*_*2yj 5

对于应用程序管理的实体管理器

EntityManager 实例不是线程安全的。

EntityManagerFactory 实例是线程安全的。

当应用程序需要访问不随 JTA 事务跨特定持久性单元中的 EntityManager 实例传播的持久性上下文时,将使用应用程序管理的实体管理器。在这种情况下,每个 EntityManager 都会创建一个新的、隔离的持久性上下文。EntityManager 及其关联的持久化上下文由应用程序显式创建和销毁。它们也用于无法直接注入 EntityManager 实例的情况,因为 EntityManager 实例不是线程安全的。EntityManagerFactory 实例是线程安全的。

欲了解更多详情,请访问这里

对于容器管理的实体管理器

EntityManager 需要在无状态会话 bean 中安全使用。