grails withTransaction - 为什么它在域对象上?

标签 grails rollback

我们需要能够回滚服务中的复杂事务,而不会向调用者抛出异常。我的理解是,实现这一点的唯一方法是使用 withTransaction。

问题是:

  • 为什么我必须在域对象上调用它,例如 Books.withTransaction
  • 如果没有相关的领域对象,那么随机选择一个的结果是什么?

  • 下面或多或少是我想要做的。用例用于从帐户中提取并将其存入信用卡。如果转账失败,我们要回滚事务,而不是回滚支付记录日志,必须在单独的事务中提交(使用 RequiresNew)。无论如何,服务方法必须返回一个复杂的对象,而不是一个异常。

    someService.groovy
    Class SomeService {
        @NotTransactional
        SomeComplexObject someMethod() {
            SomeDomainObject.withTransaction{ status ->
                DomainObject ob1 = new DomainObject.save()
                LogDomainObject ob2 = insertAndCommitLogInNewTransaction()
                SomeComplexObject ob3 = someAction()
                if (!ob3.worked) {
                     status.setRollbackOnly() // only rollback ob1, not ob2!
                }
                return ob3
            }
        }
    }
    

    以上是有缺陷的 - 我假设“返回 ob3”不会从方法中返回 ob3,因为它在一个闭包中。不确定如何从闭包内部到外部进行通信。

    最佳答案

    对于您的主要问题:如果您愿意,您可以选择一个随机域对象,它不会造成任何伤害。或者,如果您愿意,您可以找到当前 session 并在其上打开一个事务:

    grailsApplication.sessionFactory.currentSession.withTransaction { /* Do the things */ }
    

    从风格上讲,我在这里没有偏好。其他人可能。

    Not sure how to communicate from inside a closure to outside it.



    一般来说,这可能很难; withTransaction原则上可以返回任何它想要的东西,不管它的闭包参数返回什么。但事实证明,withTransaction返回其闭包返回的值。在这里,观看:
    groovy> println(MyDomainObject.withTransaction { 2 + 2 })
    4
    

    按照惯例,所有 withFoo采用闭包的方法应该以这种方式工作,正是为了让您可以做您想做的事情。

    关于grails withTransaction - 为什么它在域对象上?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30033278/

    相关文章:

    c++ - 如果在事务内数据库连接失败,如何关闭 ADO 连接

    objective-c - 如何使用Objective-C回滚对sqlite数据库执行的操作

    Grails + Tomcat6 + 多个实例 + 共享库文件夹

    ajax - 如何通过使用Grails 2.1.0中的AJAX从Grails Controller中获取数据来单击相同形式的搜索按钮时更新2个文本字段

    mysql - Grails:无法从子查询中解析 List 属性

    hibernate - 仅当子方法中发生异常时,才仅对事务进行回滚

    java - Spring Transaction - noRollbackFor 在发生异常时不会提交

    php - mysqli::commit 和 mysqli::rollback 如何工作?

    grails - Gsp 页面在替换为字符串时保留 html 标签

    hibernate - 服务方法回滚后从数据库读取对象