2010-07-27 165 views
5

有在我们的DAO层19层的方法,每一个是这一些变化:确保EntityManager连接关闭的正确方法是什么?

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。每个测试方法实例化一个灰熊容器,运行测试,然后关闭容器。 EntityManagerFactory在春季注入。我们在Hibernate上使用JPA。

我正在监视与我们的MySQL测试数据库的连接,并且它们总是很高。单独一个测试运行MySQL的“Max_used_connections”变量为38.为了好玩,我去了所有的em.close()调用,并且测试仍然使用38个连接。我使用Hibernate的内置连接池(我不知道prod的用法)。我仍然期待某种智能池。

我处理EntityManager错了吗?我还可以关闭连接吗?

+0

em.close只释放到连接池的连接。 emf.close将关闭所有连接。所以在应用程序中创建的emf可能太多,因此连接太多。 – Scarlett 2012-02-16 11:41:11

回答

2

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

5

你应该closeEntityManagerFactory在你的测试结束。从EntityManagerFactory#close()的Javadoc:

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

交易在异常情况下不会自动回滚?我终于阻止了吗? – gmoore 2010-07-28 03:15:26

+2

@gmoore:如果是JPA异常,是的。但其他人呢?我认为在finally块中调用rollback是个好习惯。 – 2010-07-28 05:08:47

+0

是的,em.close只释放连接池的连接。 emf.close将关闭所有连接。所以在应用程序中创建的emf可能太多,因此连接太多。 – Scarlett 2012-02-16 11:40:48

相关问题