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

Mysql 确保EntityManager连接关闭的正确方法是什么?,mysql,hibernate,jpa,jersey,entitymanager,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.getTrans

在我们的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测试扩展了Jersey测试。每个测试方法实例化一个Grizzly容器,运行测试,然后关闭容器。整个ManagerFactory由spring注入。我们在Hibernate上使用JPA

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

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


我是否处理EntityManager错误?还有什么方法可以关闭连接?

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

您应该在测试结束时关闭
EntityManagerFactory
。从以下文件的javadoc:

关闭工厂,释放其拥有的所有资源。关闭工厂实例后,对其调用的所有方法都将抛出
IllegalStateException
,但
isOpen
除外,后者将返回false。一旦关闭了
实体管理器工厂
,其所有实体管理器都将被视为处于关闭状态

作为补充说明,您应该在
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();
        }
    }
}

如果发生异常,事务不会自动回滚?是我的阻止阻止了吗?@gmoore:如果JPA出现异常,是的。但其他人呢?我认为在最后一个块中调用回滚是一个很好的实践。是的,EM.CHILL只释放连接池的连接。emf.close将关闭所有连接。因此,可能在应用程序中创建了太多的emf,因此获得了太多的连接。em.close仅释放到连接池的连接。emf.close将关闭所有连接。因此,您的应用程序中可能创建了太多emf,因此连接太多。
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();
        }
    }
}