2010-03-05 96 views
2

我想使用Spring提供的聲明式事務管理功能。我已經按照參考文檔(即包括AOP,tx命名空間和使用<tx:annotation-driven />標記)所述設置了Spring配置和bean,並且正在使用我希望進行事務處理的方法上的@Transactional註釋。使用@Transactional註釋問題

這是怎樣的代碼看起來像:

public interface Worker { 
    public workOnEvents(List<Events> eventsForACustomer); 
} 

public class WorkerImpl { 
    @Transactional 
    public workOnEvents(List<Events> eventsForACustomer) { 
     for(Event event : eventsForACustomer) { 
      // get DAO's based on event types at runtime, 
      // so we will have different DAO's acting within this loop 
      DAOFactory.getDAO(event.getType()).persistEvent(event); 
     } 
    } 
} 

現在,我想,如果任何在上面的循環中的DAO的無法處理的情況下,所有對數據庫的修改由來到其他的DAO製造在此之前的循環中,應該回滾。因此,爲了測試回滾,我列出了一些事件(e1,e2,e3),它們會導致DAO出現(d1,d2,d3),然後我故意拋出一個運行時異常DAO d2的persistEvent方法。但是,我得到的結果是,程序終止而不繼續循環中的事件e3,不處理拋出的異常。此外,由DAO d1保留的數據不會回滾。

請讓我知道我在這裏做錯了什麼?

+0

請添加日誌。 – Padmarag 2010-03-05 06:40:53

+0

顯示Dao工廠和一個任意的DAO類 – Bozho 2010-03-05 09:08:27

+0

我將盡快發佈DAO代碼:)我的意思是說這是我的公司擁有的代碼,並且我發佈了一些樣例代碼在這裏,它基本上模擬了正在發生的事情。至於在DAO代碼中進行刷新,我已經檢查過了,情況並非如此。它可能會受到我的應用程序中的db configs或Hibernate設置默認值的影響。不過,我會回來一些示例代碼,可以儘可能地模擬我的情況。 – abhinav 2010-03-05 09:32:03

回答

0

您需要爲註釋添加RollbackFor屬性。例如: @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Throwable.class)

+0

propagation = Propagation.REQUIRED是默認值,所以不是非常必要。 – Padmarag 2010-03-05 06:06:54

+0

這不是默認值嗎?我認爲文檔說默認情況下處理運行時異常? – abhinav 2010-03-05 06:20:28

+0

你在做一個flush()的地方 - 我看到交易被提交,如果一個刷新被稱爲... – Arvind 2010-03-05 06:24:00

0

默認情況下,只有未經檢查的異常(即java.lang.RuntimeException的子類)被回滾。

您需要將rollbackFor更改爲@Transactional註釋。

你也沒有異常處理,所以e3不會被執行。

+0

正如我所提到的,我拋出了一個RuntimeException,所以不應該是一個問題。但是,如果我捕捉到異常,它將如何傳播到Spring跨層,以便它可以回滾? – abhinav 2010-03-05 06:18:51

+0

你能不能也發佈你的DAO d2的代碼? – Padmarag 2010-03-05 06:29:07

+0

請同時添加DAO d1的代碼。某處可能存在提交/刷新。 – Padmarag 2010-03-05 06:35:09

0

也許你已經提交了前一個事務,所以Java部分不能再回滾了。

我猜想之一:

  • 您的數據庫提交每個插入/更新
  • 您的DAO做到了
1

你應該發生什麼事情都不會去會見了註解方法預期。它的工作方式是註解將方法標記爲Spring應用通知的方法,並且通知包裝方法,因此可能會在方法被調用之前發生,比如啓動新的事務,並且在方法完成之後,比如提交或回滾交易。當你描述你想讓e1和e2回滾時,那麼e3應該被提交,這將需要事務代碼在方法中間執行,所以使用這些建議是行不通的。

對於您想要的交易控制級別,您將不得不求助於Spring's programmatic transaction API

編輯:看着你的評論我可能誤解了你想要的東西。如果您可以識別要集中在一起的所有內容或全部內容,則可以將它們組合在一起,標記爲事務性的方法,並且有一個非事務性方法,該方法在具有異常處理的循環中調用該方法圍繞交易方法的每次調用。

+0

感謝您的回答。是的,我通過使用編程事務API取得了我想要的結果。 我的意圖是這樣的:對於一個客戶來說,根據今天的日期和商業規則,某些事件被挑選出來並且他們需要被處理(比如發送郵件)。但是,對於爲客戶挑選的事件的所有處理都應以事務處理的方式進行處理,因此即使發生故障,對該客戶的數據庫所做的任何更改也應該回滾。此外,處理客戶事件時遇到的錯誤不應導致應用程序終止。 – abhinav 2010-03-06 13:45:13

+0

如果我理解你是正確的,那麼如果事務處理方法適用於給定客戶的所有特定事件,並且循環和異常處理不在此範圍內,則可以使用註釋進行管理。 希望你沒有發送電子郵件作爲交易的一部分,我看到有人試圖做到這一點,並感到悲傷。 – 2010-03-06 17:53:06