服务调用成功后 Grails 不提交

Grails do not commit after a successful service call

我正在 2.4.4.

中的单个 Service 上执行以下逻辑
class SampleService {
    void process(params1, params2) {
        SampleDomain1 sd1 = new SampleDomain1()
        sd1.setProperties(params1)
        sd1.save()

        SampleDomain2 sd2 = new SampleDomain2()
        sd2.setProperties(params2)
        sd2.save()
    }
}

据我了解,Service默认情况下是事务性的。如果 sd1.save() 成功但 sd2.save() 不成功,它将回滚更改并抛出错误。如果两者都成功,则两者都在服务退出时提交。

如果我的理解是正确的,那么两者应该已经持久化到数据库中了。但是,问题是:它不会——除非您根据我使用同一组 params1params2.

的测试显式使用 flush: true 参数
        sd1.save(flush: true)

        SampleDomain2 sd2 = new SampleDomain2()
        sd2.setProperties(params2)
        sd2.save(flush: true)
    }

顺便说一下,这正是我真正要避免的(将其设置为 @Transactional 有什么意义)。如果这是 Hibernate 4 / Grails 2.4 的问题,我需要做什么才能让我的服务在每次服务调用结束时再次提交?我需要配置 Grails 的任何全局配置吗?我真的需要在每次服务结束时自动刷新我的域 类。


备注

我已经保证数据是正确的,包括调用.validate()和其他检查器。 .save(flush: true) 的成功证明了这一点。我发现的问题是 regarding to the update on Grails 2.4 在它的 FlushMode 上。现在,也许我真正需要的是一个全局设置来覆盖它。

如果您的数据没有被刷新到数据库层,我会想到一些可能性。

  1. 尝试保存到数据库时出现某种错误,您可以尝试将 failOnError=true 参数传递给 .save() 调用以清楚地看到它。 (实际上全局设置这个是个好主意,因为无声地失败的数据库调用是一种偏头痛)

  2. 您正在从同一个服务对象中调用此服务方法。由于使用代理,这将不允许底层 spring 声明性交易工作。

  3. 您可能在同一服务中注释了一些其他方法,在这种情况下,默认事务支持不再可用于剩余的 un-annotated(这甚至是一个词吗?)方法.

  4. 您可能在服务文件夹之外的某处创建了服务,不太确定这是否会导致问题,因为我从未尝试过。

  5. 您未能向 Groovy 和 Grails 之神献祭一只山羊,他们正在搅乱您的头脑。

编辑: 我将尝试回答您新编辑中的要点。

  1. 你试过 failOnError 了吗?这可能是在将两个对象同时刷新到数据库时出现的问题,而不是一次手动提交一个。

  2. 通过想出一种在保存时自动刷新的方法,您将完全绕过事务 AFAIK,现在如果我错了那么一定要去做。但是在假设之前一定要先测试一下。

在我的 DataSource.groovy 配置中的某处,有这一行:

hibernate {
        ...
        singleSession = true // configure OSIV singleSession mode
        flush.mode = 'manual' // OSIV session flush mode outside of transactional context
        ^^^^^^^^^^
}

其中明确指出每次保存都应手动刷新。作为解决方案,我注释掉了这一行。之后,每个数据库事务现在每次存在 Service.

时都会提交