0
  1. Select call leaking connections
EntityManagerFactory emf = Persistence.createEntityManagerFactory("foo");
EntityManager em = emf.createEntityManager();
Query query = em.createQuery("select bar from Bar);

Do we need to close EntityManager resources on a select call, will this leak a connection otherwise.

4

4 回答 4

3

如果您使用 EMF 创建自己的 EntityManager 实例,则需要关闭它们。

如果您在托管容器(例如 JBoss AS 或任何其他 EJB 容器)中运行,那么您可以将 EntityManger 注入到您的 bean 中,然后您不必担心关闭它。

于 2013-02-20T13:17:26.780 回答
2

我有类似的连接泄漏。根本原因是 select 语句隐式地启动了一个事务。当调用 EntityManager.close() 时,该事务仍然处于活动状态,并且由于某种原因保持连接打开。

更糟糕的是,我们的连接池永远不会回收卡在这种状态的连接。

我的解决方法是在关闭任何 entityManager 之前明确检查活动事务。我为此写了一个小辅助函数:

public static void rollbackAndClose(EntityManager mgr) {
    if (mgr != null) {
        EntityTransaction transaction = mgr.getTransaction();
        if (transaction.isActive()) {
            transaction.rollback();
        }
        mgr.close();
    }
}

(我习惯于在从 Oracle 或 SQLServer 断开 SQL 客户端时自动回滚事务,因此 EntityManager 的行为对我来说是违反直觉的。不确定 JPA 是否规定了这种行为,或者它是否特定于 Hibernate 或 MySQL。)

于 2015-01-28T03:52:25.043 回答
2

当然,总是关闭你的 EntityManagers。

于 2013-02-14T06:44:58.653 回答
0

从您显示的代码段来看,您的应用程序似乎是一个独立的应用程序,而不是在 JBoss AS 等 Java EE 容器中运行的托管应用程序或使用 Spring(为了论证起见,可以将其视为 Java EE 容器)。根据以下Wiki,您正在应用程序管理的实体管理器中运行。所以需要显式关闭实体管理器和工厂。

我想澄清一下,您需要在事务边界关闭 EntityManager。如果您将查看休眠会话的代码(EntityManagerImpl.close() 实际委托给会话关闭)。您会注意到它关闭了事务并清除了持久性上下文。关闭 EntityManagerFactory 更多的是在应用程序级别,因此您可以重用它并在销毁应用程序时关闭它。

这么说,并关注您对连接泄漏的关注,请注意连接不是由休眠直接管理的。Hibernate 有一个插件架构,允许与连接池集成。Hibernate(我认为是从 3.3 版开始,不确定)带有默认的连接池机制,不建议用于生产。如果您使用的是默认连接,则可能是连接泄漏的原因(请参阅以下帖子)。

与hibernate一起使用的最常见的连接池是C3P0(我不确定它是不是最好的......)。在非托管环境中,您需要验证连接池的配置(例如 hibernate.c3p0.* 相关的休眠属性)

于 2013-02-25T07:42:33.253 回答