保持JPA EntityManager打开?

时间:2010-08-03 02:18:38

标签: java orm jpa

我正在学习JPA,示例中的一般模式似乎如下:

EntityManager em = factory.createEntityManager();
em.getTransaction().begin();
// ....
em.getTransaction().commit();
em.close();

现在我想知道为什么我们不断创建和关闭EntityManagers,而不是保持开放并开始新的交易?保持开放与关闭它的好处和成本是什么?

2 个答案:

答案 0 :(得分:7)

有两个特定于JPA的原因:

  1. 不保证EntityManager是JPA规范的线程安全。因此,便携式JPA应用程序一次只能在一个线程中使用EM。创建方法本地EM并在它超出范围之前关闭它的习惯用法鼓励对EM引用进行堆栈限制。

  2. 使用“扩展”持久性上下文生命周期的EM为其整个存在维护单个持久性上下文。这意味着实体会在commit()上自动停止分离。相反,它们必须手动分离,否则EM仍负责跟踪它们。

  3. 这个问题实际上是旧的“何时汇集对象”问题的JPA特定版本。这是一个艰难的,但答案可能“很少”。

    Java并发专家Brian Goetz的这个old developerWorks post阐述了这一点。要点:池对于昂贵的对象(如数据库连接)非常有意义。但是对于像EntityManager这样的短期,小型和快速初始化对象,汇集或其他形式的长期参考保留是很难的。

    但是,这是一个普遍的问题,所以必然有例外。也许应用程序很简单或单线程。然后这些关于线程安全的担忧变得没有实际意义。

答案 1 :(得分:5)

保持实体管理器处于打开状态会阻止它返回与连接池的连接。

这可能导致一些问题,尤其是在Web应用程序中,例如当池运行完全且达到最大连接大小时,没有其他用户可以获得阻止该用户访问数据库的数据库连接。

在这种情况下,最好有短期生活实体经理,例如在请求开始时打开实体管理器并在请求结束时关闭它(可以使用侦听器/拦截器完成..)。然后,实体将变为分离状态,如果要再次使用它们,则必须重新附加它们(使用实体管理器的合并操作)。