服务调用成功后 Grails 不提交
Grails do not commit after a successful service call
我正在 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()
不成功,它将回滚更改并抛出错误。如果两者都成功,则两者都在服务退出时提交。
如果我的理解是正确的,那么两者应该已经持久化到数据库中了。但是,问题是:它不会——除非您根据我使用同一组 params1
和 params2
.
的测试显式使用 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
上。现在,也许我真正需要的是一个全局设置来覆盖它。
如果您的数据没有被刷新到数据库层,我会想到一些可能性。
尝试保存到数据库时出现某种错误,您可以尝试将 failOnError=true 参数传递给 .save() 调用以清楚地看到它。 (实际上全局设置这个是个好主意,因为无声地失败的数据库调用是一种偏头痛)
您正在从同一个服务对象中调用此服务方法。由于使用代理,这将不允许底层 spring 声明性交易工作。
您可能在同一服务中注释了一些其他方法,在这种情况下,默认事务支持不再可用于剩余的 un-annotated(这甚至是一个词吗?)方法.
您可能在服务文件夹之外的某处创建了服务,不太确定这是否会导致问题,因为我从未尝试过。
您未能向 Groovy 和 Grails 之神献祭一只山羊,他们正在搅乱您的头脑。
编辑:
我将尝试回答您新编辑中的要点。
你试过 failOnError 了吗?这可能是在将两个对象同时刷新到数据库时出现的问题,而不是一次手动提交一个。
通过想出一种在保存时自动刷新的方法,您将完全绕过事务 AFAIK,现在如果我错了那么一定要去做。但是在假设之前一定要先测试一下。
在我的 DataSource.groovy
配置中的某处,有这一行:
hibernate {
...
singleSession = true // configure OSIV singleSession mode
flush.mode = 'manual' // OSIV session flush mode outside of transactional context
^^^^^^^^^^
}
其中明确指出每次保存都应手动刷新。作为解决方案,我注释掉了这一行。之后,每个数据库事务现在每次存在 Service
.
时都会提交
我正在 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()
不成功,它将回滚更改并抛出错误。如果两者都成功,则两者都在服务退出时提交。
如果我的理解是正确的,那么两者应该已经持久化到数据库中了。但是,问题是:它不会——除非您根据我使用同一组 params1
和 params2
.
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
上。现在,也许我真正需要的是一个全局设置来覆盖它。
如果您的数据没有被刷新到数据库层,我会想到一些可能性。
尝试保存到数据库时出现某种错误,您可以尝试将 failOnError=true 参数传递给 .save() 调用以清楚地看到它。 (实际上全局设置这个是个好主意,因为无声地失败的数据库调用是一种偏头痛)
您正在从同一个服务对象中调用此服务方法。由于使用代理,这将不允许底层 spring 声明性交易工作。
您可能在同一服务中注释了一些其他方法,在这种情况下,默认事务支持不再可用于剩余的 un-annotated(这甚至是一个词吗?)方法.
您可能在服务文件夹之外的某处创建了服务,不太确定这是否会导致问题,因为我从未尝试过。
您未能向 Groovy 和 Grails 之神献祭一只山羊,他们正在搅乱您的头脑。
编辑: 我将尝试回答您新编辑中的要点。
你试过 failOnError 了吗?这可能是在将两个对象同时刷新到数据库时出现的问题,而不是一次手动提交一个。
通过想出一种在保存时自动刷新的方法,您将完全绕过事务 AFAIK,现在如果我错了那么一定要去做。但是在假设之前一定要先测试一下。
在我的 DataSource.groovy
配置中的某处,有这一行:
hibernate {
...
singleSession = true // configure OSIV singleSession mode
flush.mode = 'manual' // OSIV session flush mode outside of transactional context
^^^^^^^^^^
}
其中明确指出每次保存都应手动刷新。作为解决方案,我注释掉了这一行。之后,每个数据库事务现在每次存在 Service
.