2010-01-08 47 views
2

我的問題是有關交易和異常ApplicationException的 - 爪哇 - 休眠 - 回滾相關

要求:

我有10條記錄插入到數據庫表中。插入每條記錄後,我將數據插入另一個表中。所以如果插入到第二個表失敗,我想要回滾該記錄。

Ex。 說一次處理10人的現金轉移(從一個賬戶到另一個賬戶)。

僞代碼

: ------------- EJB方法的開始

for(int i = 0; i < TransferRecords.length; i++) 
{ 
    try 
    { 
      //Deduct cash from TransferRecord.accountFrom --- Includes use of Hibernate Session 
      //Add cash in TransferRecord.accountTo -- Includes use of Hibernate Session 
    } catch(AppException exception) 
    { 
      //Rollback the transaction only for this particular transfer (i) 
      // But here when I go for next record it says session is closed 
    } 
} 

--------- EJB方法結束

這裏AppException是使用@ApplicaitonException(rollback = true)annotion創建的。

我們想要的功能是:即使事務對TransferRecord失敗(比如說2),我希望數據被提交記錄0,記錄1,記錄3,記錄4(等等......但不是記錄2)

但這裏的問題是:當TransferRecord 2失敗,當我移動到TransferRecord 3,我得到「會話關閉」錯誤。

我的疑惑是: 1.這是一個正確的方法嗎?或者我應該在EJB 之外運行for循環(對於每個TransferRecord)2.如何確保會話未關閉但事務已回滾(僅限於特定失敗事務)

謝謝提前。

我正在使用EJB3,Hibernate 3.x,Jboss 4.2.x,並且我正在使用容器管理事務。

回答

2

這是一個正確的方法嗎?

不,使用CMT,您的方法是您的事務性單元。所以在這裏,你所有的TransferRecord和處理在一個相同的和獨特的交易。

順便說一句,你如何回滾交易?您是否宣傳RuntimeException或您撥打setRollbackOnly()?我只是好奇。

或者我應該在EJB之外運行for循環(對於每個TransferRecord)嗎?

爲什麼在外面?沒有什麼能強迫你這樣做。如果你要處理在自己的事務每個TransferRecord,你應該把它們傳遞給另一個 EJB方法(下面的代碼是由this answer啓發):

// supposing processRecords is defined on MyStatelessRemote1 and process defined on MyStatelessLocal1 
@Stateless 
@TransationAttribute(TransactionAttributeType.NOT_SUPPORTED) 
public class MyStatelessBean1 implements MyStatelessLocal1, MyStatelessRemote1 { 
    @EJB 
    private MyStatelessLocal1 myBean; 

    public void processRecords(List<TransferRecord> objs) { 
     // No transactional stuff so no need for a transaction here 
     for(Object obj : objs) { 
      this.myBean.process(obj); 
     } 
    } 

    @TransationAttribute(TransactionAttributeType.REQUIRES_NEW) 
    public void process(TransferRecord transferRecord) { 
     // Transactional stuff performed in its own transaction 
     // ... 
    } 
} 

我怎樣才能確保會議不關閉但交易回滾(僅針對特定交易失敗)

我想我已經介紹了該部分。

+0

新鮮實體管理器之外感謝Pascal。順便說一句,你如何回滾交易?你是否傳播一個RuntimeException或者你調用setRollbackOnly()?我只是好奇。 我們只拋出RuntimeException。 我們正試圖避免整體上的用戶交易。但是你的代碼很有前途。 再次感謝。 – 2010-01-08 19:59:29

+0

我不確定是否有僞代碼,但我沒有添加任何東西:) – 2010-01-08 20:33:54

0

我認爲你可以創建兩個獨立的事務,第一個是TransferRecord(1)(一旦一切正常就進行提交),然後爲所有TransferRecord(i + 1)啓動其他TX。

另一種方法是使用保存點,可以回滾並丟棄超過該保存點的所有內容(但我更喜歡第一種方法)。

問候。

1

你在這裏唯一的選擇是要麼使用用戶的交易,而不是循環的容器管理事務的bean中,以便進入豆說每次你得到相關的事務和連接(基本會話)

+0

您可以使用CMT並在bean內循環。 – 2010-01-08 20:38:46

+0

帕斯卡, 你的意思是: 使用:@TransationAttribute(TransactionAttributeType.REQUIRES_NEW) 公共無效過程(TransferRecord transferRecord){ 樣的方法和循環通過另一種方法,所有TransferRecords? 謝謝。 – 2010-01-09 04:23:38