java – EntityManager真的是线程安全的吗?

前端之家收集整理的这篇文章主要介绍了java – EntityManager真的是线程安全的吗?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我在说这里的基本用法
@Stateless
public class BookServiceBean implements BookService {
  @PersistenceContext EntityManager em;
  public void create(Book book) { this.em.persist(book);}
}

谷歌搜索上述问题,StackOverflow说yes,but no – 接受的答案是肯定的,但后续的是否定的; Spring.io说both yes and no,而似乎是Java EE专家的Adam Bien给出了unqualified yes.@H_301_5@

我对一个简单的预定bean的经验表明答案是否定的:@H_301_5@

@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;
  }
}

抽象界面:@H_301_5@

@Local
public interface TimerTickAbs {
  public Runnable runner();
}

开始于:@H_301_5@

@Resource ManagedScheduledExecutorService managedExecutorService;
@EJB TimerTick myRunner;

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

如果我打印出Thread.currentThread().getId(),即使我仍然在调用之间的同一个线程上,我得到:@H_301_5@

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

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

解决方法

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

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

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

猜你在找的Java相关文章