成功的服务调用后,Grails不会提交

时间:2016-01-15 08:39:45

标签: grails gorm transactional

我在 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()不成功,则会回滚更改并抛出错误。如果两者都成功,两者都会在服务退出时承诺。

如果我的理解是正确的,那么它们都应该已经保存到数据库中。但是,问题是:它不会 - 除非您使用同一组flush: trueparams1基于我的测试明确使用params2参数。

        sd1.save(flush: true)

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

顺便提一下,我真正避免的是什么(将其设置为@Transactional)。如果这是Hibernate 4 / Grails 2.4的捕获,那么我需要做些什么来使我的服务再次在服务调用的每一端提交?我是否需要配置Grails的任何全局配置?我真的需要在每个服务结束时自动刷新我的Domain类。

<小时/>

注意

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

2 个答案:

答案 0 :(得分:2)

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

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

  2. 您正在同一服务对象中调用此服务方法。由于使用代理,这将不允许底层的spring声明式事务处理。

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

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

  5. 你没有向Groovy和Grails Gods牺牲一只山羊,他们正在弄乱你的头。

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

    1. 您是否尝试过failOnError?当两个对象一次刷新到DB时,可能会出现问题,而不是一次手动提交一个。

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

答案 1 :(得分:1)

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

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

哪个明确指出应该手动刷新每个保存。作为解决方案,我注释掉这一行。之后,每次存在Service时,每个数据库事务都会提交。