Đinh Hồng Châu
Đinh Hồng Châu

Reputation: 5440

Transaction when saving many object in Grails service

I am having a problem with transaction in Grails. I want to save a list of object to DB by a checking condition at each object. All these process I want to put to one transaction, it means if the k-th object does not satisfied the checking condition, all previous objects (from the first object to the (k-1)th one) will be rolled back from DB. Here is my example:

static transactional = true

public void saveManyPeople() {
    // ...
    List<People> peoples = new ArraysList();
    for(i = 0, i < n, i++) {
         People newPeople = createPeopleFromRawData(); // return a people object in memory
         if(<checking-condition>) {
              newPeople.save(flush : false)  
         } else {
               throw new MyCustomizedException()  // MyCustomizedException has extended from RuntimException
         }
    }
    // ...
}

As you may see, I set transactional variable to true and I've tried to use flush : true and flush : false, but it didn't work as I want. I've read this article Rolling back a transaction in a Grails Service And the author recommended that the service method should throw a RuntimeException then the process will be rollbacked. But if I want to throw another exception, so what I have to do? Could you please give me some suggestions on this problem? Thank you so much!

Upvotes: 1

Views: 3379

Answers (2)

Derek Slife
Derek Slife

Reputation: 22496

Could you verify that saveManyPeople() is within a Service and not a Controller?

The static transactional = true isn't respected in a Controller. I am suspecting that this is the issue.

If you need to have transactional support with the controller, you could always use DomainClass.withTransaction. Reference Documentation Example:

Account.withTransaction { status ->
    def source = Account.get(params.from)
    def dest = Account.get(params.to)
    def amount = params.amount.toInteger()
    if(source.active) {
        source.balance -= amount
        if(dest.active) {
            dest.amount += amount
        }
        else {
            status.setRollbackOnly()
        }
    }   
}

Upvotes: 0

deluan
deluan

Reputation: 1865

You can throw any exception that extends from RuntimeException to rollback the transaction. Or you can use Programmatic Transactions, using withTransation, to have more control over the transaction.

Upvotes: 0

Related Questions