2014-02-19 77 views
2

我試圖實施以下情形:Grails的人工交易和回滾

class A { 
    ... 
    static hasMany = [bees: B] 
} 

class B { 
    static belongsTo = [a: A] 
} 

現在,我們創造約10,000 B的情況下(從服務)在某時刻屬於一個A,但如果1失敗它應該回滾所有成功創建的。我已經嘗試了一些方法,沒有工作:

try { 
    for (int i = 0; i < batch.numToMake; i++) { 
     def b = new B().save(flush: i % 1000 == 0) 

     if (i == 50) { 
      throw new RuntimeException("simulate") 
     } 
    } 

    batch.status = Constants.BATCH_STATUS_DONE 
    batch.save(flush: true) 
} catch (e) { 
    // This was a last resort test and still did not work 
    batch.status = Constants.BATCH_STATUS_FAILED 
    batch.vouchers.each { 
     batch.removeFromVouchers(it) 
    } 

    batch.save(flush: true) 
} 

// This did not work at all 
B.withTransaction { status -> 
    try { 
     for (int i = 0; i < batch.numToMake; i++) { 
      def b = new B().save(flush: i % 1000 == 0) 

      if (i == 50) { 
       throw new RuntimeException("simulate") 
      } 
     } 
    } catch (e) { 
     status.setRollbackOnly() 
    } 
} 

誰能幫幫忙我怎麼可以創造大量的的hasMany /屬於關聯關係的項目,但回滾一切失敗1,從服務類。


+0

點3 [這個答案](http://stackoverflow.com/a/17357547/2051952)是我假設你正在使用grails服務,在這種情況下假設你是最好的選擇。 – dmahapatro

回答

0

的服務需求是事務性的(把Grails的服務類的頂部@Transactional註釋),那麼你就不需要try/catch語句。從該方法拋出的任何RuntimeException將觸發事務回滾。 所以,你可以簡單地做到以下幾點:

def import() { 
    def a = A.get(1L) 
    for (int i = 0; i < 1000; i++) { 
     new B(a: a).save() 

     // runtime exception thrown here would rollback everything 
    } 
} 

你需要照顧同批次工作的時候是什麼,以確保會議不會增長太大。您可以防止通過得到的句柄當前會話,然後沖洗和清除:從

def import() { 
    Parent.withSession { session -> 
     def a = A.get(1L) 
     for (int i = 0; i < 10000; i++) { 
      new B(a: a).save() 

      // runtime exception thrown here would rollback everything 

      if (i % 100 == 0) { 
       session.flush() 
       session.clear() 
      } 

      // runtime exception thrown here would rollback everything 
     } 
    }