Search code examples
grailstransactionsgrails-orm

Grails - Saving multiple object, Rollback all object if one fails to save


I need to save multiple object at once, and rollback all if one object fails to save. For example :

class Transaction {
  Item item;
}

class Item {
  date lastTransaction;
}

If I create new Transaction, I need to change lastTransaction value and save the item.
If I failed to save the item, I need to rollback the Transaction (vice versa).

Any ideas?


Solution

  • Yuck. Don't throw exceptions to roll back transactions. You're incurring a pretty high cost to take advantage of a side effect where the transaction manager, assuming that a runtime exception means that you're not in control, automatically rolls back the transaction for you to keep you from doing more damage. It's a bit like being lonely and hitting yourself in the head repeatedly with a hammer so some EMTs and perhaps a nurse or a doctor will spend some time with you.

    It's pretty easy to roll back a transaction, but unfortunately Grails doesn't expose any of this:

    import org.springframework.transaction.interceptor.TransactionAspectSupport
    
    class FooService {
    
       def someMethod(...) {
    
          boolean somethingBadHappened = ...
          if (somethingBadHappened) {
             // roll back
             TransactionAspectSupport.currentTransactionStatus().setRollbackOnly()
          }
    
          // ok, proceed
          ...
       }
    }
    

    And later you can check if the current transaction was rolled back with

    TransactionAspectSupport.currentTransactionStatus().isRollbackOnly()
    

    Note that this won't work in a controller since the transaction will have ended by that point.