EntityManager 真的是线程安全的吗? [英] Is EntityManager really thread-safe?

查看:58
本文介绍了EntityManager 真的是线程安全的吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在这里谈论的是基本用法:

I'm talking about the basic usage here:

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

谷歌搜索上述问题,StackOverflow 说是,但不是 - 接受的答案说是,但后续行动是否;Spring.io 说 是和否,似乎是 Java EE 专家的 Adam Bien 给出了一个 不合格是.

Googling the above question, StackOverflow says yes, but no - the accepted answer says Yes, but a followup is No; Spring.io says both yes and no, and Adam Bien, who seems to be a Java EE expert, gives an unqualified yes.

我自己使用一个简单的预定 bean 的经验表明答案是否定的:

My own experience with a simple scheduled bean suggests the answer is NO:

@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(),即使我在两次调用之间仍然在同一个线程上,我得到:

If I print out the Thread.currentThread().getId(), even though I am still on the same thread between calls, I get:

严重:java.lang.IllegalStateException:试图在关闭的 EntityManager 上执行操作

SEVERE: java.lang.IllegalStateException: Attempting to execute an operation on a closed EntityManager

我知道我可以做像 @PersistenceUnit private EntityManagerFactory emf; 的代码并自己管理 EntityManager,但我想利用所有自动事务的东西@PersistenceContext 给我的.

I know I can do code like @PersistenceUnit private EntityManagerFactory emf; and manage the EntityManager myself, but I'd like to take advantage of all the automatic transaction stuff that @PersistenceContext gives me.

推荐答案

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

No, an EntityManager is NOT thread safe. Adam Bien though is also correct. You are just not looking at the question correctly. The question he is answering isn't if an EntityManager is thread safe, he is stating that using container managed EntityManger in a stateless session bean is safe, which it is. He then explains the reasoning and wording of the spec that allows the container to work its magic - "each instance sees only a serialized sequence of method calls". That allows container injection to have different EntityManager contexts per method invocation, similar to how each invocation can be tied to their own transaction and isolated resources.

注入实际上只是注入一个 EntityManager 代理,该代理使容器可以控制下面的 JPA EntityManager 的生命周期,从而将其绑定到线程和事务.

Injection is really just injecting an EntityManager proxy that gives the container control over the lifecycle of the JPA EntityManagers underneath, allowing it to be tied to the thread and the transaction.

所以 EntityManager 不是线程安全的,但容器注入的 EntityManager 代理需要在无状态会话 bean 中安全使用.

So an EntityManager is NOT thread safe, but the container injected EntityManager proxies are required to be safe to use within stateless session beans.

这篇关于EntityManager 真的是线程安全的吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆