5

There are 19 methods in our DAO layer, each is some variation of this:

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();
    }
}

Meaning: In each method we handle our own transaction and close it in a finally block. We're testing a Jersey app, so our JUnit tests extend JerseyTest. Each test method instantiates a Grizzly container, runs the test, then shuts down the container. EntityManagerFactory is injected by spring. We're using JPA over Hibernate.

I'm monitoring the connections to our MySQL test DB and they're always high. One test alone runs the MySQL "Max_used_connections" variable to 38. For fun, I went and commented out all the em.close() calls, and the test still uses 38 connections.

I'm using Hibernate's built-in connection pooling (not for prod use, I know). I still expected some sort of intelligent pooling.

Am I handling the EntityManager wrong? How else can I close connections?

4

2 回答 2

5

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

void javax.persistence.EntityManagerFactory.close()

关闭工厂,释放它拥有的所有资源。关闭工厂实例后,对其调用的所有方法都将抛出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();
        }
    }
}
于 2010-07-27T23:22:52.943 回答
2

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

于 2010-07-27T21:45:36.450 回答