2010-07-27 169 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

相關問題