开发者

Rolling back a transaction in a Grails Service

开发者 https://www.devze.com 2023-01-02 04:00 出处:网络
I have been updating all my services to be transactional by using Grail\'s ability to rollback when a RuntimeException is thrown in the service. I have, in most cases, doing this:

I have been updating all my services to be transactional by using Grail's ability to rollback when a RuntimeException is thrown in the service. I have, in most cases, doing this:

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

Anyways, I wanted to verify that this indeed will rollback the transaction... it got me thinking as to whether at this point it's already been committed.. Also, if not, would setting flush:true change t开发者_JS百科hat? I am not very familiar with how Spring/Hibernate does all of this :)


Yep that'll do it.

Transactions in Grails are by default handled at a Service method level. If the method returns normally then the transaction will be committed, if a RuntimeException is thrown the transaction will be rolled back.

Note this means even if you use flush:true on while saving an object in the server method the db changes will still be rolled back if you throw a RuntimeException.

For example:

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")
   }                                                           
 }
}

What I'm not 100% clear on with Grails is what happens if a checked exception is thrown in straight java/spring world the default behaviour is for the transaction inceptor to commit the transaction, althrough this can be overriden in the config.

Note: there is a caveat, and that is that your db has to support transactions on the tables you are updating. Yes, this is poke at MySQL :)

This also applies to the Domain.withTransaction method.


Just wanted to add additional comments to the accepted answer, and this was too long to fit into a comment.

What I'm not 100% clear on with Grails is what happens if a checked exception is thrown

By default, the exception must NOT be checked, or the transaction won't be rolled back. Apparently that's a Spring thing.

If you really want to check the exceptions on a method, you can explicitly mark the service method as @Transactional and use the rollbackFor argument to list which exceptions should still cause a rollback. (Note that I haven't actually tested this.)

Be aware, though, that marking any one method in a service with @Transactional disables the automatic wrapping of its other methods with a transaction. So, if you do it for one, you have to do it for all of them. Be sure you really need to declare those checked exceptions ;)

You can read more about this at http://docs.grails.org/latest/guide/services.html.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号