保持JPA EntityManager打开?

问题描述:

我学习JPA和实例的一般模式似乎如下:保持JPA EntityManager打开?

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

现在我想知道为什么我们不断创造和接近EntityManagers,而不是保持它的开放和刚刚开始新的交易?保持开放与始终关闭的好处和成本有哪些?

JPA特定

两个原因浮现在脑海中:

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

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

这个问题是一个真正的JPA特定版本的旧“何时池对象”的问题。这是一个艰难的,但答案可能是“很少”。

这个old developerWorks post由Java并发专家Brian Goetz阐述了这一点。要点:池对于昂贵的对象很有意义,比如数据库连接。但对于像EntityManager这样的短暂,小而快速初始化的对象,共享或其他形式的长期参考保留是一种难以推销的方式。

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

保持一个实体管理器打开可以防止它返回到连接池的连接。

这可能导致几个问题,尤其是在web应用程序中,例如,当池运行已满且达到最大连接大小时,其他用户无法获得阻止该用户访问数据库的数据库连接。

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