【问题标题】:Does a Java EE container automatically close an injected EntityManagerFactory?Java EE 容器是否会自动关闭注入的 EntityManagerFactory?
【发布时间】:2014-04-02 18:38:58
【问题描述】:

假设我在@Stateless Enterprise JavaBean 中有这段代码:

@PersistenceUnit
EntityManagerFactory emf;

Java EE 容器迟早会自动关闭我的EntityManagerFactory

规格说明

Java Persistence specification, version 2.1 在第 338 页上说以下内容:

当应用程序使用完实体管理器工厂后, 和/或在应用程序关闭时,应用程序应关闭 实体管理器工厂。

好的,这很简单。我必须关闭工厂。

但是,由于我首先注入了工厂,所以我有点紧张自己调用 close() 方法。如果容器并不比在下一个想要工厂的 bean 中重用一个封闭的工厂更聪明怎么办?此外,我不喜欢添加很多管道来将我自己的逻辑与应用程序关闭时发生或不发生的情况挂钩。此外,我没有打开/创建工厂只是闻起来很糟糕,但我的代码负责关闭它。对于这个问题,大量的 Java EE 规范肯定有更多要告诉我的吗?

嗯.. 。我在 JPA 2.1 和 EJB 3.2 规范中看到的注入工厂的示例并没有显式关闭它。这些示例只有在通过 Persistence.createEntityManagerFactory() 显式创建工厂时才会关闭它(请参阅 JPA 2.1 规范,第 345 和 355 页)。

我看到的关于容器职责的唯一讨论来自 JPA 2.1 规范页面 356:

[..] 容器需要支持第三方持久化 提供者,在这种情况下,容器必须使用 PersistenceProvider.createContainerEntityManagerFactory 方法来 创建实体管理器工厂和 EntityManagerFactory.close 在关闭之前销毁实体管理器工厂的方法(如果它 之前没有被应用程序关闭)。

这里说容器确实有责任关闭工厂。但让我几乎不相信最后这句话的是,示例/引用清楚地谈到了一个非常特殊的用例,即容器使用“第三方持久性提供程序”。

对我来说,如果我阅读 EJB 3.2 规范中从第 286 页开始的关于持久性单元引用的章节,这个话题会变得更加混乱。在这里,没有关于谁承担的字眼关闭实体管理器工厂的责任 - 我或容器。

我的结论是,通过复制规范中使用的示例,我应该或者更确切地说必须是安全的。这意味着我不必明确关闭工厂。让我感到困惑的是,我在 JPA 规范中使用的第一句话清楚地表明我必须关闭工厂!

你的意见是什么?我错过了什么吗?

【问题讨论】:

  • 由于 EMF 是由容器为您创建的,它也应该为您关闭它。不过,我很难找到参考资料。
  • 我的推理是一样的。
  • 我知道这不是答案,但通常你注入 EntityManager 而不是 EntityManagerFactory
  • 我需要一个用于特定用例的应用程序管理的 EntityManager。

标签: jakarta-ee containers entitymanager java-ee-7


【解决方案1】:

由于EntityManagerFactory 是由您的容器创建的,它负责其生命周期(并因此关闭它)。只有一个EMF,因此除非在应用程序生命周期结束时关闭它,否则将毫无意义。来自JPA 2.1 spec 9.1 节:

[...]

作为结果获得的 EntityManagerFactory 实例将被 容器来创建容器管理的实体管理器。 只有一个 允许为每个部署创建 EntityManagerFactory 持久性单元配置。 任意数量的 EntityManager 实例 可以从给定的工厂创建。

但是,如果您决定通过注入的EMF 自行管理EntityManager,则您有责任关闭它。

【讨论】:

  • 您引用了有关持久性上下文和实体管理器的规范。不是持久化单元,实体管理器工厂。它们是两种不同的东西。
  • 我不这么认为。 7.8.1 明确提到应用程序管理的持久化上下文需要通过 EntityManagerFactory.close() 关闭 EMF,而 7.8.2 说容器透明地管理持久化上下文。
  • 7.8.1 没有这么说。 7.8.2 确实谈到了持久化上下文,也就是实体管理器。我再次谈到持久化单元,即实体管理器工厂。 7.8.2 还说实体管理器可能会被池化,在这种情况下,他将永远不会被容器关闭。我的推理与您完全一样,可以肯定地说容器也管理注入的实体管理器工厂的生命周期。奇怪的是我的问题中的第一句话引用了规范说我们需要明确关闭工厂。
  • 第一个引用并不奇怪。这只是一般性声明,即如果应用程序(容器或非托管)使用 EMF 完成,则应始终关闭它。它与托管环境中的应用程序没有直接关系。
  • 在我的报价开始之前,规范说:“应用程序使用 EntityManagerFactory 接口来获取应用程序管理的实体管理器”。所以上下文是一个注入的实例,“应用程序”必须是我的代码;我的代码负责关闭工厂。规范中哪里有说谁负责关闭工厂?您编辑的答案带有重要的引用,必须断定这是容器的责任。不幸的是,我仍然认为我使用的报价正好相反。
猜你喜欢
  • 1970-01-01
  • 2021-03-07
  • 1970-01-01
  • 2011-02-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-09
  • 1970-01-01
相关资源
最近更新 更多