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

gmo*_*ore 5 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();
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

Pas*_*ent 5

你应该closeEntityManagerFactory 你的测试结束.来自javadoc EntityManagerFactory#close():

void javax.persistence.EntityManagerFactory.close()
Run Code Online (Sandbox Code Playgroud)

关闭工厂,释放它所拥有的任何资源.关闭工厂实例后,在其上调用的所有方法都会抛出IllegalStateException,但是isOpen会返回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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @gmoore:如果是JPA例外,是的.但其他人呢?我认为在finally块中调用rollback是一个很好的做法. (2认同)

a1e*_*x07 2

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