Question

I need to save and update properties of different domain classes in one transaction.

I know I can use the following:

def addToChildren(String name, int age) {
    User.withTransaction {
        def user = new User(name)
        user.age = age
        user.save()

        def school = new School()
        school.addToUsers(user)
        school.save()
    }
}
  1. Is it possible to use transactions like this in a domain model?
  2. Where should I put the addToChildren function? Is it in the User class, the School class or some external place like a Service?
  3. Should I use withTransaction or withNewTransaction?
  4. Can I have transactions in model function?
  5. Should addToChildren be a model function which calls a service function to modify the model properties?
Was it helpful?

Solution

Grails services already are transactional, and it's the best place to manipulate domain classes. The documentation explains it:

Services are typically involved with coordinating logic between domain classes, and hence often involved with persistence that spans large operations. Given the nature of services, they frequently require transactional behaviour. You can use programmatic transactions with the withTransaction method, however this is repetitive and doesn't fully leverage the power of Spring's underlying transaction abstraction.

So there's no need to use withTransaction inside them.

EDIT

Where should I put the addToChildren function?

This is more a design decision you can declare you method in a domain class or in a service. Personally, when I manipulate more than one domain class I tend to do it in a service class, except when I need to use the GORM events: beforeInsert(), beforeUpdate() and beforeDelete().

Can I have transactions in model function?

Yes, you can use transactions / hibernate sessions in your domain class. A common example is the beforeDelete event:

class Person {
   String name
   def beforeDelete() {
      ActivityTrace.withNewSession {
         new ActivityTrace(eventName: "Person Deleted", data: name).save()
      }
   }
}

Since you're deleting a record, you need a new hibernate session to handle others inserts.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top