确保EntityManager连接关闭的正确方法是什么?

时间:2010-07-27 21:26:21

标签: mysql hibernate jpa jersey entitymanager

我们的DAO层有19种方法,每种方法都有一些变体:

public TicketProp saveTicketProp(TicketProp prop) {
    EntityManager em = this.emf.createEntityManager();
    try {
        em.getTransaction().begin();
        prop = (TicketProp) em.merge(prop);
        em.getTransaction().commit();
        return prop;
    } finally {
        em.close();
    }
}

含义:在每个方法中,我们处理自己的事务并在finally块中关闭它。我们正在测试Jersey应用程序,因此我们的JUnit测试扩展了JerseyTest。每个测试方法都实例化一个Grizzly容器,运行测试,然后关闭容器。 EntityManagerFactory由spring注入。我们使用JPA而不是Hibernate。

我正在监控与MySQL测试数据库的连接,它们总是很高。一个测试单独运行MySQL“Max_used_connections”变量为38.为了好玩,我去了所有em.close()调用注释,测试仍然使用38个连接。

我正在使用Hibernate的内置连接池(我知道不是用于prod使用)。我仍然期待某种智能汇集。

我处理EntityManager错了吗?我怎么能关闭连接?

2 个答案:

答案 0 :(得分:5)

您应该在测试结束时close EntityManagerFactory 。来自EntityManagerFactory#close()的javadoc:

void javax.persistence.EntityManagerFactory.close()
     

关闭工厂,释放它所拥有的任何资源。关闭工厂实例后,在其上调用的所有方法都将抛出IllegalStateExceptionisOpen除外,它将返回false。一旦EntityManagerFactory关闭,其所有实体经理都被视为处于关闭状态。

作为旁注,您应该在关闭finally子句中的EM之前回滚事务:

public TicketProp saveTicketProp(TicketProp prop) {
    EntityManager em = this.emf.createEntityManager();
    try {
        em.getTransaction().begin();
        prop = (TicketProp) em.merge(prop);
        em.getTransaction().commit();
        return prop;
    } finally {
        if (em.getTransaction().isActive()) {
            em.getTransaction().rollback();
        }

        if (em.isOpen()) {
            em.close();
        }
    }
}

答案 1 :(得分:2)

为什么你认为EntityManager.close()总是在物理上关闭底层连接?这取决于连接池(您可能需要配置它并设置同时打开的连接的最大数量)。