在Grails服务中保存许多对象时的事务

时间:2011-04-04 13:28:26

标签: grails transactions rollback

我在Grails中遇到了交易问题。我想通过每个对象的检查条件将对象列表保存到DB。我希望将所有这些过程放到一个事务中,这意味着如果第k个对象不满足检查条件,则所有先前的对象(从第一个对象到第(k-1)个)将从DB回滚。这是我的例子:

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,并且我尝试使用flush:true和flush:false,但它没有按我的意愿工作。我读过这篇文章Rolling back a transaction in a Grails Service 并且作者建议服务方法应抛出RuntimeException然后该进程将被回滚。但是,如果我想抛出另一个异常,那么我必须做什么? 你能否就这个问题给我一些建议? 非常感谢你!

2 个答案:

答案 0 :(得分:0)

您可以抛出从RuntimeException扩展的任何异常以回滚事务。或者,您可以使用Programmatic Transactions使用withTransation来更好地控制交易。

答案 1 :(得分: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()
        }
    }   
}