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

Joh*_*tle 4 grails rollback

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

问题是:

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

以下是我正在尝试做的或多或少.用例是从帐户中提取并将其放入信用卡.如果传输失败,我们想要回滚事务,而不是支付记录日志,这必须在单独的事务中提交(使用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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

Dav*_*ler 8

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

grailsApplication.sessionFactory.currentSession.withTransaction { /* Do the things */ }
Run Code Online (Sandbox Code Playgroud)

从文体上来说,我没有偏好.其他人可能.

不确定如何从闭包内部到外部进行通信.

总的来说这可能很难; withTransaction原则上可以返回它想要的任何东西,无论它的闭包参数返回什么.但事实证明,它withTransaction返回其闭包返回的值.在这里,观看:

groovy> println(MyDomainObject.withTransaction { 2 + 2 })
4
Run Code Online (Sandbox Code Playgroud)

按照惯例,所有withFoo采用闭包的方法都应该以这种方式工作,这样才能完成你想要做的事情.