2012-08-30 23 views
3

我在我的glassfish服務器上有一個奇怪的問題。看看這段代碼:EntityManager不需要的背景提交

userTransaction.begin(); 

MyEntity entity = new MyEntity(12345); 
//setting values.. 
entityManager.persist(entity); 

MyEntity persistedEntity = entityManager.createQuery("SELECT p FROM MyEntity p WHERE p.idpk=12345").getSingleResult(); 
//... 

userTransaction.commit(); //OK => the tuple is in the DB 

現在有一個業務問題,事務需要回滾。

​​

即使回滾似乎工作(沒有發生異常或奇怪的日誌輸出),元組已在數據庫中,一直致力於... 要搜索的問題是,我想下面的代碼:

userTransaction.begin(); 

MyEntity entity = new MyEntity(12345); 
//setting values.. 
entityManager.persist(entity); 

//Business problem => rollback 
userTransaction.rollback(); //OK => the tuple 12345 is NOT in the DB ! 

通過此代碼(實體未被檢索),該元組不會被提交給數據庫,這是正確的行爲。讓我們走的更遠:

userTransaction.begin(); 

MyEntity entity = new MyEntity(12345); 
//setting values.. 
entityManager.persist(entity); 

MyEntity persisted = entityManager.find(MyEntity.class, 12345); 
//... 

//Business problem => rollback 
userTransaction.rollback(); //OK => the tuple 12345 is NOT in DB 

在最後這種情況下,結果仍然是正確的,也沒有元組提交到數據庫。看起來EntityManager使用查詢檢索實體時會發出一個奇怪的[不需要的]提交... 我也嘗試在另一個表上進行查詢,並且不會導致錯誤的提交(回滾工作)。此外,我試圖在自己的服務器上重現問題,並且沒有任何問題:所有回滾都正常工作。因此,它應該真的是一個服務器配置問題。

有關信息,它是在linux上運行的glassfish v2.1.1。 EntityManager在FlushModeType.AUTO中。

有沒有人有想法?

謝謝&最好的問候!

+0

什麼是您的jpa提供程序? – dcernahoschi

+0

我正在使用OpenJPA 1.2.1 – ctabin

+0

您使用的是哪個數據庫?這個問題的表在兩個數據庫上都有相同的DDL(如果它們不同)? – dcernahoschi

回答

0

我終於找到了在那裏有問題:在JDBC連接池,還有一節「交易「選項」非事務性連接「已啓用...只需刪除此選項使整個事情工作:)

2

發現了一些討論,這似乎是你看到的解釋一些:

通過P-331 EJB3在行動書:

默認情況下,數據庫刷新模式設置爲AUTO 。這意味着實體管理器根據需要自動執行刷新操作。 通常,這發生在事務範圍內的實體管理器的事務結束時,以及對應用程序託管或擴展範圍EntityManagers關閉的持久性上下文爲 時發生。 此外,如果在查詢中使用了具有掛起更改的實體,則 持久性提供程序將在執行查詢之前刷新對數據庫的更改。如果刷新模式設置爲COMMIT,則 持久性提供程序將僅在事務提交時與數據庫同步。但是,您應該注意這一點,因爲在執行查詢之前,它將負責將實體狀態與數據庫 同步。如果您不這樣做並且EntityManager查詢返回來自數據庫的陳舊實體,則應用程序可能會以不一致的狀態結束。

P-353 EJB3在行動書指出:

如果查詢設爲FlushModeType.COMMIT,更新 的持久化上下文的實體做出的效果不被定義 規範,實際行爲是特定於實現的。

也許嘗試切換上查詢刷新模式通過

entityManager.createQuery("SELECT p FROM MyEntity p WHERE p.idpk=12345").getSingleResult();

或實體管理器本身並返回看看是否改變任何東西?

一些進一步的討論在這裏:

http://www.coderanch.com/t/475041/ORM/databases/EntityManager-setFlushMode-COMMIT-Vs-Query

+0

你好,我已經調查過這個解決方案。在我的情況下,它可以工作,但會導致其他問題(特別是在FlushModeType.COMMIT中,更新查詢的行爲未指定)。我認爲這個問題實際上並不在FlushModeType中,而是在服務器的配置中...... – ctabin

0

爲什麼不能做到這一點:

MyEntity persisted = entityManager.persist(entity); 
+0

是的,它可以工作,但是應用程序真的很大,持久化在另一部分完成,我不能直接檢索實體... – ctabin

+0

你在同一個交易中這樣做,對吧? – siebz0r

+0

是的。問題實際上是「爲什麼事務的回滾在這種情況下不起作用」。我想有一些配置(無論是在MySQL或Glassfish),使這種情況發生。 – ctabin