2011-04-04 31 views
1

我在Grails中遇到了事務問題。我想通過每個對象的檢查條件將對象列表保存到數據庫。我想把所有這些過程放到一個事務中,這意味着如果第k個對象不滿足檢查條件,所有先前的對象(從第一個對象到第(k-1)個對象)將從DB回滾。這是我的例子:在Grails服務中保存很多對象時的事務

static transactional = true 

public void saveManyPeople() { 
    // ... 
    List<People> peoples = new ArraysList(); 
    for(i = 0, i < n, i++) { 
     People newPeople = createPeopleFromRawData(); // return a people object in memory 
     if(<checking-condition>) { 
       newPeople.save(flush : false) 
     } else { 
       throw new MyCustomizedException() // MyCustomizedException has extended from RuntimException 
     } 
    } 
    // ... 
} 

正如你可能會看到,我設置交易變量設置爲true,我試着使用沖水:true和沖洗:假的,但我想它沒有工作。我讀過這篇文章Rolling back a transaction in a Grails Service 而且作者建議服務方法應該拋出一個RuntimeException,然後該進程將被回滾。但是如果我想拋出另一個異常,那我該怎麼辦? 您能否就這個問題給我一些建議? 非常感謝!

+0

它是如何工作呢?你從哪裏打來電話,是否可以通過其他服務撥打? – 2011-04-04 13:35:09

+0

嗨,維克多,函數saveManyPeople()在我的服務類中,這個函數將從控制器調用,而不是從另一個服務類。謝謝! – 2011-04-04 16:37:21

回答

0

您可以拋出任何從RuntimeException延伸的異常來回滾事務。或者,您可以使用Programmatic Transactions(使用withTransation)對交易進行更多控制。

0

你能證實saveManyPeople()在服務內而不是控制器嗎?

static transactional = true在控制器中不受尊重。我懷疑這是個問題。

如果您需要對控制器進行事務支持,則始終可以使用DomainClass.withTransaction。 Reference Documentation 例如:

Account.withTransaction { status -> 
    def source = Account.get(params.from) 
    def dest = Account.get(params.to) 
    def amount = params.amount.toInteger() 
    if(source.active) { 
     source.balance -= amount 
     if(dest.active) { 
      dest.amount += amount 
     } 
     else { 
      status.setRollbackOnly() 
     } 
    } 
} 
+0

嗨Derek,函數saveManyPeople()和我在服務類中定義的事務變量。你的例子看起來像控制器類的片段,不是嗎? AFAIK,我們可以通過設置transactional = true來自動處理Grails服務中的事務,而無需做更多事情。但在我的情況下,當一些以前的對象已經存儲到數據庫時,雖然我拋出了一個RuntimeException(MyCustomizedException從它延伸出來),但它不能回滾。謝謝! – 2011-04-04 16:47:59

+0

作爲測試,當您設置transactional = false並管理您自己的編程事務(Domain.withTransaction&setRollbackOnly())時會發生什麼?這可能會縮小問題範圍。如果它表現出相同的行爲,那麼我們可能需要開始查看您的數據庫/ jdbc/transactionManager設置。 – 2011-04-05 03:47:55

相關問題