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

grails withTransaction - why is it on a domain object?

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

问题是:

  1. 为什么我必须在域对象上调用它,例如 Books.withTransaction
  2. 如果没有相关领域对象怎么办,随便挑一个会有什么后果?

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

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

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

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

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

在风格上我对这里没有偏好。其他人可能会。

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

总的来说这可能很难; withTransaction 原则上可以 return 任何它想要的东西,不管它的闭包参数 return 是什么。但事实证明,withTransaction return 的值是 return 由它的闭包编辑的。在这里,观看:

groovy> println(MyDomainObject.withTransaction { 2 + 2 })
4

按照惯例,所有采用闭包的 withFoo 方法都应该以这种方式工作,这样您就可以做您想做的事情。

我假设这个问题来自 grails 2 应用程序,这个 2015 年的问题已经在现在之前得到解决。

我在任何 grails 2 文档中都找不到这个,但是服务有一个神奇的 transactionStatus 变量注入到它们的方法中。 (至少在 grails 2.3.11 中)

您可以关闭所有注释并使用注入的变量。

Class SomeService {
    SomeComplexObject someMethod() {
        DomainObject ob1 = new DomainObject.save()
        LogDomainObject ob2 = insertAndCommitLogInNewTransaction()
        SomeComplexObject ob3 = someAction()
        if (!ob3.worked) {
             transactionStatus.setRollbackOnly() // transactionStatus is magically injected.
        }
        return ob3
    }
} 

此功能在 grails 2 中,但未记录。它记录在 grails 3 中。 https://docs.grails.org/latest/guide/services.html#declarativeTransactions

搜索 transactionStatus