在Grails服务中回滚事务

Rya*_*nch 13 grails spring hibernate transactions

通过使用Grail在服务中抛出RuntimeException时回滚的能力,我一直在将所有服务更新为事务性的.在大多数情况下,我这样做:

def domain = new Domain(field: field)
if (!domain.save()) {
   throw new RuntimeException()
}
Run Code Online (Sandbox Code Playgroud)

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

Gar*_*vis 16

是的,这样做.

默认情况下,Grails中的事务处理服务方法级别.如果方法正常返回,那么将提交事务,如果抛出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")
   }                                                           
 }
}
Run Code Online (Sandbox Code Playgroud)

如果在直接的java/spring世界中抛出一个已检查的异常,那么我不会100%明白Grails的情况,默认行为是事务处理器提交事务,通过这可以在配置中覆盖.

注意:有一个警告,那就是您的数据库必须支持要更新的表上的事务.是的,这是在MySQL的戳:)

这也适用于该Domain.withTransaction方法.

  • 是的,任何 RuntimeException 都会强制回滚,而 InnoDB 对于 MySQL 来说是一个不错的选择,只有在你发现你真的需要性能时才烦恼其他表类型 (2认同)