开发者

grails rollback db operation on some error

I have a service where to save a lot of data to db. Using MYSQL I have used like this

Domain1.withTransaction {text->
            def domain1=//Create my domain object to save 
             if(!domain1.save()){
               domain1.errors.each {
                      println it
               }
               throw new RuntimeException('unable to save domain1')
        }
        Domain2开发者_开发百科.withTransaction {text->
            def domain2=//Create my domain object to save 
             if(!domain2.save()){
               domain2.errors.each {
                      println it
               }
               throw new RuntimeException('unable to save domain2')
        }

My problem if there occurred any problem in saving domain2 i need to roll back domain1 save also.

I need to remove domain1 from db.


Instead of using programatic transaction handling, the Service artifact allows for automatic transaction handling. This typically leads to cleaner and more maintainable code.

You can also use the failOnError:true when you save() to force a RuntimeException to be thrown.

Example below:

class SomeService {

    static transactional = false

    def serviceMethod() {
        def domain1=//Create my domain object to save
        def domain2=//Create my domain object to save
        domain1.save(failOnError:true)
        domain2.save(failOnError:true)
    }
}

UPDATE

I'm revisiting this topic, after I read a response to another topic. Grails Integration Test Does NOT Rollback

Please verify that your dialect is setup as InnoDB as MyISAM tables aren't transactional. This is configured in your Config.groovy

dataSource {
      dialect= org.hibernate.dialect.MySQLInnoDBDialect
      ...
}


Try removing the Domain2.withTransaction {text-> part. You are already inside a transaction with your first call. If you do further work inside the brackets, you should stay within the same transaction and domain1 should be rolled back if you throw and exception after checking domain2.


Put that Domain2.withTransaction closure inside Domain1.withTransaction closure, so error in Domain2 transaction will rollback both Domain1 and Domain2 transaction
Like this

Domain1.withTransaction {
      //....
      Domain2.withTransaction {
           //....
      } 
} 


If you just want a single transaction which is rolled back when an unhandled unchecked exception is thrown, then don't start a nested transaction. The necessaary code changes are shown below:

Domain1.withTransaction {text->
  def domain1=//Create my domain object to save 
  if (!domain1.save()) {
    domain1.errors.each {
      println it
    }
    throw new RuntimeException('unable to save domain1')
  }

  def domain2=//Create my domain object to save 
    if (!domain2.save()) {
      domain2.errors.each {
        println it
      }
    throw new RuntimeException('unable to save domain2')
  }
}
0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜