我在grails 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: true
和params1
基于我的测试明确使用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。现在,也许我真正需要的是全局设置来覆盖它。
答案 0 :(得分:2)
如果您的数据没有被刷新到数据库层,那么可以想到一些可能性。
尝试保存到数据库时出现某种错误,您可以尝试将failOnError = true参数传递给.save()调用以清楚地看到它。 (实际上在全球范围内设置这个是一个好主意,因为无声的db调用是偏头痛)
您正在同一服务对象中调用此服务方法。由于使用代理,这将不允许底层的spring声明式事务处理。
您可能在同一服务中注释了其他一些方法,在这种情况下,默认的事务支持不再可用于剩余的未注释(这甚至是一个单词?)方法。
< / LI>您可能已经在服务文件夹之外的某个位置创建了服务,不太确定这是否会导致问题,因为我从未尝试过。
你没有向Groovy和Grails Gods牺牲一只山羊,他们正在弄乱你的头。
编辑: 我将尝试回答您新修改中的要点。
您是否尝试过failOnError?当两个对象一次刷新到DB时,可能会出现问题,而不是一次手动提交一个。
通过找出一种在保存时自动刷新的方法,你将完全绕过交易AFAIK,现在如果我错了,那么一定要去做。但是在假设之前先测试一下。
答案 1 :(得分:1)
在DataSource.groovy
配置的某处,有这一行:
hibernate {
...
singleSession = true // configure OSIV singleSession mode
flush.mode = 'manual' // OSIV session flush mode outside of transactional context
^^^^^^^^^^
}
哪个明确指出应该手动刷新每个保存。作为解决方案,我注释掉这一行。之后,每次存在Service
时,每个数据库事务都会提交。