在Grails服务中回滚事务

时间:2010-06-05 09:15:25

标签: spring hibernate grails transactions

我一直在使用Grail在服务中抛出RuntimeException时回滚的能力来更新我的所有服务。在大多数情况下,我这样做:

def domain = new Domain(field: field)
if (!domain.save()) {
   throw new RuntimeException()
}

无论如何,我想验证这确实会回滚事务......它让我思考在这一点上它是否已经被提交了。另外,如果没有,会设置flush:true会改变吗?我不太熟悉Spring / Hibernate如何完成所有这些:)

2 个答案:

答案 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标记服务中的任何一个方法都会禁用其他方法与事务的自动包装。所以,如果你为一个人做,那么你必须为所有人做这件事。确保你真的需要来声明那些经过检查的异常;)

您可以在http://docs.grails.org/latest/guide/services.html了解详情。