【问题标题】:Transaction when saving many object in Grails service在 Grails 服务中保存许多对象时的事务
【发布时间】:2011-04-04 13:28:25
【问题描述】:

我在 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 然后进程将被回滚。但是如果我想抛出另一个异常,那我该怎么办? 你能给我一些关于这个问题的建议吗? 非常感谢!

【问题讨论】:

  • 那它是如何工作的呢?你从哪里调用它,它是从另一个服务调用的吗?
  • 嗨 Victor,函数 saveManyPeople() 在我的服务类中,这个函数将从控制器调用,而不是从另一个服务类调用。谢谢!

标签: grails transactions rollback


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    您能否验证 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()
            }
        }   
    }
    

    【讨论】:

    • 嗨 Derek,我在服务类中定义的函数 saveManyPeople() 和事务变量。您的示例看起来像控制器类中的 sn-p,不是吗? AFAIK,我们可以通过设置 transactional = true 来自动处理 Grails 服务中的事务,而无需做更多的事情。但在我的情况下,虽然我抛出了一个 RuntimeException(MyCustomizedException 从它扩展),但当一些以前的对象存储到 DB 时无法回滚,这很奇怪。谢谢!
    • 作为一个测试,当您设置 transactional=false 并管理您自己的编程事务(Domain.withTransaction 和 setRollbackOnly())时会发生什么?这可能会缩小问题范围。如果它表现出相同的行为,那么我们可能需要开始查看您的 database/jdbc/transactionManager 设置。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-04-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-10
    • 1970-01-01
    相关资源
    最近更新 更多