2012-10-24 81 views
30

我有一個具有propagation = Propagation.REQUIRES_NEW事務屬性的方法:Spring的事務:回滾事務

@Transactional(propagation = Propagation.REQUIRES_NEW) 
public void createUser(final UserBean userBean) { 
    //Some logic here that requires modification in DB 
} 

這種方法可以同時調用多次,並且對每一項交易如果不是發生錯誤它回滾(獨立於其他交易)。

問題是這可能會強制Spring創建多個事務,即使另一個可用,並且可能會導致一些性能問題。


propagation = Propagation.REQUIRED Java的醫生說:Support a current transaction, create a new one if none exists.

這似乎解決了性能問題,不是嗎?

回滾問題呢?如果在使用現有事務時新方法調用回滾會怎麼樣?即使是以前的調用,是不是會回滾整個事務?

[編輯] 我想我的問題是不夠清楚:

我們有數百個連接到我們的服務器的客戶端。

對於每個客戶端,我們自然需要發送有關事務的反饋(確定或異常 - >回滾)。

我的問題是:如果我使用REQUIRED,意思只有一個事務時,如果客戶端100遇到問題第一客戶端的事務將回退呢?

+1

還有點兒REQUIRES_NEW點,創造新的交易每個方法被調用的時間。是的,如果你有REQUIRED並且事務回滾了,它會回滾整個事情。 –

+0

@DenisTulskiy整個事情是每一個以前的調用,或當前的調用堆棧? –

+2

@jidma:整個交易,見@尤金的答案,如果'createUser'是您的客戶端代碼調用的第一個方法,然後REQUIRES_NEW和要求的是同一個東西 –

回答

48

使用REQUIRES_NEW僅在從事務上下文中調用方法時才相關;當方法從非事務性上下文調用時,它的行爲將與REQUIRED完全相同 - 它將創建一個新的事務。

這並不意味着您的所有客戶端只會有一個單一事務 - 每個客戶端都將從非事務性上下文開始,只要請求處理命中@Transactional,它就會創建一個新的交易。因此,考慮到這一點,如果使用REQUIRES_NEW對於該操作的語義有意義 - 比我不擔心性能 - 這會導致教科書不成熟的優化 - 我寧願強調正確性和數據完整性,並擔心性能一旦收集到績效指標,而不是之前。

回滾 - 使用REQUIRES_NEW將強制執行新事務的開始,所以異常會回滾事務。如果還有另一個正在執行的事務 - 根據操作的具體情況,將根據異常是否冒出堆棧或被捕獲 - 根據您的選擇進行回滾或不回滾。 此外,有關的交易策略和回滾一個更深入的討論,我會建議:«Transaction strategies: Understanding transaction pitfalls», Mark Richards

+0

能否請你看一下這個問題https://stackoverflow.com/questions/44539861/spring-transactional-commit-failures-deby-eclipselink? 做我需要做以後一段時間,它得到了回滾pesist後給予回覆'REQUIRES_NEW',響應。 – vels4j

10

如果您確實需要在單獨的事務中執行此操作,則需要使用REQUIRES_NEW並承擔性能開銷。注意死鎖。

我寧願做它的其他方式:

  • 在Java端驗證數據。
  • 在一次交易中運行everyting。
  • 如果DB端發生任何錯誤 - >這是數據庫或驗證設計的主要錯誤。回滾一切並拋出重要的頂級錯誤。
  • 編寫好的單元測試。
+0

我們有數百個連接到我們的服務器的客戶端。對於每個客戶端,我們需要發送有關事務的反饋(確定或異常 - >回滾)。我的問題仍然是:如果我使用'REQUIRED',是否意味着只使用一個事務,並且如果第100個客戶遇到問題,則第一個客戶的事務將回滾? –