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

发布于 2024-10-29 04:45:06 字数 944 浏览 1 评论 0原文

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

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,但它没有按我想要的方式工作。我读过这篇文章回滚 Grails 服务中的事务 并且作者建议服务方法应该抛出一个RuntimeException,然后进程将被回滚。但是如果我想抛出另一个异常,那么我该怎么办? 您能否就这个问题给我一些建议? 太感谢了!

I am having a problem with transaction in Grails. I want to save a list of object to DB by a checking condition at each object. All these process I want to put to one transaction, it means if the k-th object does not satisfied the checking condition, all previous objects (from the first object to the (k-1)th one) will be rolled back from DB. Here is my example:

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
         }
    }
    // ...
}

As you may see, I set transactional variable to true and I've tried to use flush : true and flush : false, but it didn't work as I want. I've read this article Rolling back a transaction in a Grails Service
And the author recommended that the service method should throw a RuntimeException then the process will be rollbacked. But if I want to throw another exception, so what I have to do?
Could you please give me some suggestions on this problem?
Thank you so much!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

万劫不复 2024-11-05 04:45:06

您可以抛出任何从 RuntimeException 扩展的异常来回滚事务。或者,您可以使用 程序化事务,使用 withTransation 来对交易有更多的控制权。

You can throw any exception that extends from RuntimeException to rollback the transaction. Or you can use Programmatic Transactions, using withTransation, to have more control over the transaction.

追星践月 2024-11-05 04:45:06

您能否验证 saveManyPeople() 位于服务中而不是控制器中?

控制器中不遵守static transactional = true。我怀疑这就是问题所在。

如果您需要控制器的事务支持,您始终可以使用 DomainClass.withTransaction。 参考文档
例子:

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()
        }
    }   
}

Could you verify that saveManyPeople() is within a Service and not a Controller?

The static transactional = true isn't respected in a Controller. I am suspecting that this is the issue.

If you need to have transactional support with the controller, you could always use DomainClass.withTransaction. Reference Documentation
Example:

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()
        }
    }   
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文