保持 JPA EntityManager 的开放?

2022-09-03 07:33:15

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

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

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


答案 1

我想到了两个JPA特定的原因:

  1. 根据 JPA 规范,EntityManager 不保证是线程安全的。因此,可移植 JPA 应用程序一次最多只能在一个线程中使用 EM。创建方法局部 EM 并在超出范围之前将其关闭的习惯用语鼓励对 EM 引用的堆栈限制。

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

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

Java并发专家Brian Goetz的这篇老开发人员Works帖子阐述了这一点。要点:池对于昂贵的对象(如数据库连接)非常有意义。但对于短期、小型和快速初始化的对象(如 EntityManager),池化或其他形式的长期引用保留很难销售。

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


答案 2

使实体管理器保持打开状态可防止其返回与连接池的连接。

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

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


推荐