我们是不是需要在选择调用时关闭 EntityManager 资源
Posted
技术标签:
【中文标题】我们是不是需要在选择调用时关闭 EntityManager 资源【英文标题】:Do we need to close EntityManager resources on a select call我们是否需要在选择调用时关闭 EntityManager 资源 【发布时间】:2013-02-14 04:01:47 【问题描述】:-
选择呼叫泄漏连接
EntityManagerFactory emf = Persistence.createEntityManagerFactory("foo"); EntityManager em = emf.createEntityManager(); Query query = em.createQuery("select bar from Bar);
我们是否需要在选择调用时关闭 EntityManager 资源,否则会泄漏连接。
【问题讨论】:
【参考方案1】:如果您使用 EMF 创建自己的 EntityManager 实例,则需要关闭它们。
如果您在托管容器中运行(例如 JBoss AS 或任何其他 EJB 容器),那么您可以将 EntityManger 注入到您的 bean 中,然后您不必担心关闭它。
【讨论】:
【参考方案2】:当然,总是关闭你的 EntityManagers。
【讨论】:
+1 ...除非您使用容器管理的持久性上下文(OP 没有) 我的是一个独立的应用程序,所以我不知道如何管理这个,我们似乎有泄漏无关我是否添加一个 em.close() 调用 连接泄漏仍然存在,与我是否关闭EntityManager无关【参考方案3】:我有类似的连接泄漏。根本原因是 select 语句隐式地启动了一个事务。当调用 EntityManager.close() 时,该事务仍然处于活动状态,并且由于某种原因保持连接打开。
更糟糕的是,我们的连接池从未回收卡在此状态的连接。
我的解决方法是在关闭任何 entityManager 之前明确检查活动事务。我为此写了一个小辅助函数:
public static void rollbackAndClose(EntityManager mgr)
if (mgr != null)
EntityTransaction transaction = mgr.getTransaction();
if (transaction.isActive())
transaction.rollback();
mgr.close();
(我习惯于在将 SQL 客户端与 Oracle 或 SQLServer 断开连接时自动回滚事务,因此 EntityManager 的行为对我来说是违反直觉的。不确定 JPA 是否规定了这种行为,或者它是否特定于 Hibernate 或 mysql .)
【讨论】:
【参考方案4】:从您显示的 sn-p 看来,您的应用程序是独立的,而不是在 JBoss AS 等 Java EE 容器或 Spring 中运行的托管应用程序(为了论证,可以将其视为 Java EE 容器) . 根据以下Wiki,您正在应用程序管理的实体管理器中运行。所以需要显式关闭实体管理器和工厂。
我想澄清一下,您需要在事务边界处关闭 EntityManager。如果您将查看休眠会话的代码(EntityManagerImpl.close() 实际委托给会话关闭)。您会注意到它关闭了事务并清除了持久性上下文。关闭 EntityManagerFactory 更多的是在应用程序级别,因此您可以重用它并在销毁应用程序时关闭它。
这么说,并关注您对连接泄漏的关注,请注意连接不是由休眠直接管理的。 Hibernate 有一个插件架构,允许与连接池集成。 Hibernate(我认为从 3.3 版开始,不确定)带有默认的连接池机制,不推荐用于生产。如果您使用的是默认设置,则可能是连接泄漏的原因(请参阅以下post)。
与hibernate一起使用的最常见的连接池是C3P0(我不确定它是不是最好的......)。 在非托管环境中,您需要验证连接池的配置(例如 hibernate.c3p0.* 相关的休眠属性)
【讨论】:
以上是关于我们是不是需要在选择调用时关闭 EntityManager 资源的主要内容,如果未能解决你的问题,请参考以下文章
当我们调用函数时,如果没有像func这样的参数传递,则需要参数括号();与函数(); [关闭]