2012-01-15 160 views
1

EntityManger注入了@PersistenceContext註釋。這是我的「DAO/Repository」類沒有註釋的一種方法。這個類被注入到需要從/到數據庫中獲取數據的EJB中。EntityManager.persist()後會發生什麼

到現在爲止,我認爲在下面的persist方法完成後,persistencecontext被刷新並且數據被存儲到數據庫,但是從我的應用程序中發生的事情開始懷疑這一點。我已經在Glassfish中創建了數據源和連接池,因此我使用容器管理事務,但是我沒有使用任何事務註釋。

難道有人能爲我提供一些啓示嗎?

public void persist(QuestionFeedback questionFeedback) { 
    questionFeedback.setCreated(new Date()); 
    entityManager.persist(questionFeedback); 
} 

中使用GlassFish 3,Java的兼容性EE6

回答

0

如果你不使用任何交易說明,將被要求的默認交易。因此,您的DAO將在事務中運行,並且持久化上下文將不會在事務提交時被刷新。

根據JavaDoc上TransactionAttribute

如果未指定TransactionAttribute註釋,而Bean使用容器管理事務劃分,假設所需的事務屬性的語義。

從JavaDoc的上FlushModeType

當查詢在事務內執行,如果FlushModeType.AUTO被設定在查詢或TypedQuery對象,或者如果在沖洗模式設置爲持久性上下文是AUTO(缺省值)並且沒有爲Query或TypedQuery對象指定刷新模式設置,持久性提供程序負責確保持久化上下文中可能影響查詢結果的所有實體的狀態的所有更新對查詢的處理是可見的。

這意味着如果您使用的查詢的結果可能受該flush的影響,可能會更早地刷新持久化上下文。

3

persist方法使實體持久化,但尚未將更改寫入數據庫。這通常發生在事務提交時(提供者可以自由優化這個,它可能會更早發生)。

使用flush您可以強制寫入更早發生,但它仍然只對參與當前事務的代碼可見。要使寫入永久(對所有外部代碼都可見),事務仍然需要提交。

沒有任何明確的註釋,你的EJB bean默認是事務性的。

0

因爲EntityManager是通過@PersistenceContext註釋注入的,所以您肯定使用容器管理的事務。

無論如何,你的假設,堅持導致交易提交是錯誤的。通過持續執行的更改在提交時發送到數據庫。 EntityManager的文檔說,「通過調用persist,新實例變爲託管和持久性」。在這種情況下,「變得持久」並不意味着實體在那一刻持續存在於數據庫中。在調用persist的那一刻,實體被持久化爲PersistenceContext。然後,在事務提交時,最後持久化到數據庫。

因爲您沒有對您的方法使用任何@TransactionAttribute註釋,所以將應用默認值。默認是TransactionAttributeType.REQUIRED。這會導致容器在第一個業務方法被調用時創建事務並將其傳播到其他方法。您的交易將在完成對第一個業務方法的調用時提交。然後您的更改在數據庫中(如果沒有執行回滾)。

+0

所以你在說什麼是業務方法打開和關閉事務(在我的代碼中調用上面的持久方法的那個),然後事務被提交?或者我誤解了你? – LuckyLuke 2012-01-15 14:05:54

+0

是的,如果調用persist方法的方法的客戶端沒有事務上下文。然後在你的情況下,容器必須在方法的開始和結束時保持對事務的開始和提交的關注。如果客戶端有現有的事務,那麼你的方法加入到這個事務中,並且提交發生在客戶端的某個地方。沒有定義的事務屬性,這些方法調用有多少層並不重要,邏輯保持不變:在第一個事務中啓動並提交事務。 – 2012-01-15 14:17:41