afterUpdate事件挂钩,事务和连续请求中的旧状态

时间:2016-11-24 17:06:16

标签: grails transactions gorm

我们遇到了一个奇怪的问题,即第一个请求中创建了对象,但是第二个请求中没有返回它们。 假设我们有两个域类:

Class A {
    static hasMany = [bs: B]

    def afterUpdate() {
        this.addToBs(new B(a: this))
        this.save()
    }
}

Class B {
    static belongsTo = [a: A]
}

当通过PUT /as/<id>在A的实例上发送了广告时,update()会在RestfulController注释@Transactional

我们可以观察到,在返回第一个请求的响应之后,API消费者每隔一段时间发送一个后续请求,GET /bs不会返回B的新实例。已在第一个请求中创建,并在进一步请求时返回。

我预计一旦提交了事务,grails只会将响应发送给API使用者,这意味着下一个请求应该看到该事务的所有更改,不应该吗?

这种行为可能是什么原因?在grails应用程序已将响应发送给API使用者之后,事务是否已提交?如果是这样,@Transactional围绕update()默认启用的原因是什么?

我知道在这个示例中,afterUpdate中的代码也可能被放入beforeUpdate,但我只是尽力简化示例。

1 个答案:

答案 0 :(得分:0)

根据我的经验,afterUpdate()中的代码等不包含在交易中。您必须明确创建一个事务(也可能是一个会话)。见http://docs.grails.org/latest/ref/Domain%20Classes/withTransaction.html

我建议afterUpdate()和朋友中的GORM更新,因为它会导致这样的奇怪问题,并且难以对域模型进行单元测试。如果您将保存委托给事务服务,不仅可以正常工作,还可以通过集成测试进行确认。

在我的Grails应用程序中,我保持控制器非常愚蠢:

  1. 致电服务
  2. 返回服务的输出(可能将其格式化)。
  3. 我将所有业务逻辑保留在服务中,因为控制器很难测试。这是一个例子:

    @grails.transaction.Transactional
    class SomeService {
        def saveA(A a) {
            // This method will run in a transaction.
            a.addToBs(new B(a: this))
            a.save()
        }
    }
    

    在控制器......

    class SomeController {
        def update() {
            ...
            someService.save(a)
        }
    }