当前位置: 首页 > 知识库问答 >
问题:

是否应该关闭JPA实体管理器?

喻选
2023-03-14
public Profile readUser(String email){
    EntityManager em = EMF.get().createEntityManager();
    return em.find(Profile.class, email);
}

实体管理器的上述用法可以吗?或者有必要关闭EM?有什么建议请。

共有1个答案

甄文彬
2023-03-14

我想答案是:这要看情况而定。

您的实体管理器是访问实体所在上下文的关键。如果您的应用程序是一个JSE应用程序,那么您必须考虑上下文的预期寿命是多少。

让我们考虑您将根据用户的请求创建一个实体管理器。因此,当您处理给定的请求时,您将保持实体管理器打开,当您完成它时,您将关闭它。

在JSE应用程序中,您可能已经考虑过希望在应用程序的整个生命周期中保持实体管理器打开(假设您不处理大量数据),然后在应用程序关闭时关闭它。

底线,你什么时候打开,什么时候关闭,完全取决于你的策略和你的设计。当您不再需要其上下文中的实体时,您将关闭它。

在您的示例中,这一点并不明显,但由于您是在方法中创建EM,因此在返回之前应该关闭它,否则,您将不再有权访问它(除非您将它保存在某个注册表中,这在代码中并不明显)。

如果您不关闭它,那么您的实体将保持为附加的状态,即使在您使用完它们之后也是如此。即使您无法再访问EM,您的上下文也将保持活动。

JPA规范包含更多细节。在第7.7节应用程序管理的持久性上下文中,它说:

当使用应用程序管理的实体管理器时,应用程序直接与持久性提供者的实体管理器工厂交互,以管理实体管理器生命周期,并获取和销毁持久性上下文。

EntityManagerFactory.CreateEntityManager方法以及EntityManagerCloseIsOpen方法用于管理应用程序管理的实体管理器的生命周期及其关联的持久性上下文。

扩展持久性上下文从使用EntityManagerFactory.CreateEntityManager创建实体管理器开始,直到通过EntityManager.Close关闭实体管理器为止。

从应用程序管理的实体管理器获得的扩展持久化上下文是一个独立的持久化上下文,它不与事务一起传播。

[...]EntityManager.Close方法关闭实体管理器以释放其持久性上下文和其他资源。调用close后,应用程序不得在EntityManager实例上调用任何其他方法,但GetTransactionIsOpen除外,否则将引发IllegalStateException。如果在事务处于活动状态时调用close方法,则持久性上下文将保持托管状态,直到事务完成。

EntityManager.isOpen方法指示实体管理器是否已打开。在实体管理器关闭之前,isopen方法返回true。要真正理解它是如何工作的,理解实体管理器和上下文之间的关系是至关重要的。

因此,正如您所看到的,实体管理器是您访问实体的公共接口,然而,您的实体驻留在连接到实体管理器的上下文中。理解不同类型上下文的生命周期将回答您的问题。

持久性上下文可以是不同的类型。在Java EE应用程序中,既可以有事务范围的持久性上下文,也可以有扩展的持久性上下文。在JSE应用程序中,上下文的性质由开发人员html" target="_blank">控制。

当您向您的实体管理器请求一个实体时,它会在其附加的上下文中查找该实体,如果它在那里找到该实体,则返回该实体,否则,它会从数据库中检索该实体。在上下文中对此实体的后续调用将返回相同的实体。

事务范围

@PersistenceContext(unitName="EmplService")
EntityManager em;

在带有有状态会话bean的Java EE应用程序中,您可能希望上下文能够经受多次bean调用,因为您不喜欢在bean被标记为删除之前提交,对吗?在这些情况下,您需要使用扩展的持久性上下文。在这种情况下,持久性上下文是在第一次需要时创建的,但它不会变得无效,直到您标记了要删除的有状态bean。

@PersistenceContext(unitName="EmplService", type=PersistenceContextType.EXTENDED)

这意味着,无论在有状态会话bean方法的后续调用中注入到这个bean的实体管理器的实例是什么,您都可以确信您将始终访问相同的上下文,因此,即使后续调用也将返回相同的实例,因为它是相同的上下文。

而且,在bean被标记为要删除或者手动刷新之前,您的更改不会被刷新。

应用程序管理

您始终可以手动实例化您的实体管理器工厂和您的实体管理器。这是您在JSE应用程序中通常要做的,对吗?

对于这类应用程序,您通常没有容器来处理JTA事务,对吗?因此您使用资源本地事务,并负责手动提交或回滚更改。

 类似资料:
  • 问题内容: 我有下面的方法。 实体管理器的上述用法可以吗?或者有必要关闭em吗?有任何建议。 问题答案: 我想答案是: 取决于 。 您的实体管理员是获得对实体所在上下文访问权限的关键。如果您的应用程序是JSE应用程序,则必须考虑上下文的​​预期寿命是多少。 让我们考虑您将根据用户的请求创建一个实体管理器。因此,在您处理给定的请求时,您将保持实体管理器处于打开状态,完成后将其关闭。 在JSE应用程序

  • 我在一个JavaSE项目中使用EclipseLink作为JPA提供者。我已经正确地配置了编织,以允许延迟加载。 与HiberNate(抛出LazyPresalizationExctive)不同,Eclipse Link可以获得LAZY关系的代理,即使是在封闭的实体管理器中。要运行此查询,它从池中获得一个新连接。 是否存在禁用或更改此功能行为的设置?在尝试访问未加载的属性(如Hibernate)时,

  • 在我的实际应用程序中,我有一个业务层,它根据一些业务规则使用JPA来持久化数据,问题是camel JPA事务没有与业务层事务共享。我需要业务类中的EntityManager与Camel事务范围集成,我该怎么做? 下面是一个简单的例子,但这反映了实际设计中的问题。 项目实例 服务级别 骆驼路线 骆驼背景。xml

  • 我使用的是Spring BOOT应用程序,它将信息存储在数据库中。我得到错误: org.SpringFramework.transaction.CanNotCreateTransactionException:无法为事务打开JPA EntityManager 还尝试了AutoReconnect=true,在db URL中提供了端口号。

  • 我试图使用spring boot将EntityManager注释注入到我的DAO中,但是得到一个< code > InvalidDataAccessApiUsageException 消息,说没有可用的事务EntityManager。我的印象是,只要Spring Boot从< code>application.yml中获得了我的数据源信息,并且我用< code>@PersitenceContext

  • 我正在使用Spring的事务支持和JPA(Hibernate)来持久化我的实体。一切正常,但我在处理一个请求中的部分更新时陷入困境: 对于每个用户(HTTP)请求,我必须将一个日志条目写入数据库表,即使“主”业务实体的更新失败(例如,由于验证错误)。因此,我的第一个/主要事务get被回滚,但第二个(写日志)应该提交。这似乎可以使用正确的传播级别来写入日志条目: 然而,我的问题是,我在第二个事务中注