2014-03-13 49 views
1

我想了解JPA中的事務是什麼。JPA中的事務實現

說我有部署持久性的GlassFish應用程序:

<?xml version="1.0" encoding="UTF-8"?> 
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> 
    <persistence-unit name="survex" transaction-type="JTA"> 
    <jta-data-source>jdbc/MyDatabase</jta-data-source> 
    <exclude-unlisted-classes>false</exclude-unlisted-classes> 
    <properties> 
    </properties> 
    </persistence-unit> 
</persistence> 

我試圖調試代碼sniffering請求MySQL服務器:

public String create() { 

     EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("survex"); 
     EntityManager em = entityManagerFactory.createEntityManager(); 
     Log log = em.find(Log.class, 1); 

     EntityTransaction transaction = em.getTransaction(); 
     transaction.begin(); // NOTING HAPPENS ... 
     log.setMessage("xxx"); 
     em.flush(); // OH, HERE IT IS -> SET autocommit=0; UPDATE LOG SET message = 'xxx' WHERE (id = 1) 
     log.setMessage("aaa"); 
     em.flush(); // OK -> UPDATE LOG SET message = 'aaa' WHERE (id = 1) 
     transaction.commit(); // NOTHING HAPPENS! WHERE IS COMMIT?! 

     log = em.find(Log.class, 1); 

     transaction = em.getTransaction(); 
     transaction.begin(); // STILL NOTHING ... 
     log.setMessage("555"); 
     em.flush(); // UPDATE LOG SET message = '555' WHERE (id = 1) 
     log.setMessage("666"); 
     em.flush(); // UPDATE LOG SET message = '666' WHERE (id = 1) 
     transaction.commit(); // NOTHING!!! 

     return log.getMessage(); 
    } 
    // SOMEWHERE OUTSIDE: COMMIT; SET autocommit=1; 

爲什麼?爲什麼JPA表現得如此奇怪?

我希望在每次transaction.commit()調用時提交,或者我誤解了某些內容?

+1

認爲你需要.comfl後的.flush –

+1

否,.commit後的.flush會導致異常。 – corvax

回答

1

我在代碼中看到一個問題:您將PersistenceContext定義爲JTA,但使用RESOURCE_LOCAL事務API(即EntityManager.getTransaction())。

由於您處於Java EE環境中,只需獲取注入的實例UserTransaction@Resource private UserTransaction transaction;EntityManager而不是創建一個實例。你也應該禁用CMT(容器管理)事務,否則它們會自動打開/關閉。

+0

我認爲你是對的!原因我得到以下異常:無法使用SynchronizationType創建EntityManager,因爲PersistenceUnit在嘗試執行此操作時配置了資源本地事務 - entityManagerFactory.createEntityManager(SynchronizationType.SYNCHRONIZED);你能提供正確使用的代碼示例嗎? – corvax

+1

當然可以。但我建議你閱讀這篇關於EntityManagers類型的非常好的文章http://piotrnowicki.com/2012/11/types-of-entitymanagers-application-managed-entitymanager/,並決定如何編寫代碼。如果你想在不閱讀的情況下嘗試它,谷歌將EntityManager注入到Servlet或EJB中,因爲要寫更多的東西。 –