我一直在使用Grail在服务中抛出RuntimeException时回滚的能力来更新我的所有服务。在大多数情况下,我这样做:
def domain = new Domain(field: field)
if (!domain.save()) {
throw new RuntimeException()
}
无论如何,我想验证这确实会回滚事务......它让我思考在这一点上它是否已经被提交了。另外,如果没有,会设置flush:true会改变吗?我不太熟悉Spring / Hibernate如何完成所有这些:)
答案 0 :(得分:15)
是的,这样做。
Grails中的事务默认在Service方法级别处理。如果方法正常返回,那么将提交事务,如果抛出RuntimeException,则将回滚事务。
注意这意味着即使在服务器方法中保存对象时使用flush:true,如果抛出RuntimeException,仍会回滚db更改。
例如:
class MyService {
def fiddle(id,id2){
def domain = Domain.findById(id)
domain.stuff = "A change"
domain.save( flush:true ) // will cause hibernate to perform the update statements
def otherDomain = OtherDomain.findById(id2)
otherDomain.name = "Fiddled"
if( !otherDomain.save( flush:true )){ // will also write to the db
// the transaction will be roled back
throw new RuntimeException("Panic what the hell happened")
}
}
}
我不是100%明白使用Grails,如果在直接的java / spring世界中抛出一个检查异常会发生什么情况,默认行为是事务感知器提交事务,通过这可以在配置中覆盖
注意:有一点需要注意,那就是您的数据库必须支持要更新的表上的事务。是的,这是对MySQL的捅:)
这也适用于Domain.withTransaction
方法。
答案 1 :(得分:2)
只是想在接受的答案中添加其他评论,这太长了,不适合评论。
如果抛出已检查的异常,我不会100%清楚Grails的内容
默认情况下,不得检查异常,否则不会回滚事务。显然这是一个春天的事情。
如果您确实要检查方法的异常,可以将服务方法显式标记为@Transactional
,并使用rollbackFor
参数列出哪些异常仍应导致回滚。 (请注意,我实际上没有对此进行测试。)
请注意,使用@Transactional
标记服务中的任何一个方法都会禁用其他方法与事务的自动包装。所以,如果你为一个人做,那么你必须为所有人做这件事。确保你真的需要来声明那些经过检查的异常;)