3

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?
Michael
  • 32,527
  • 49
  • 210
  • 370

1 Answers1

10

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.

  • Ok, this does not answer my question. Where should I put the addToChildren function? Can I have transactions in model function? Should addToChildren be a model function which calls a service function to modify the model properties? – Michael Nov 01 '13 at 13:06
  • When should I use withNewSession and when withSession? – Michael Nov 01 '13 at 22:37
  • withSession use the same already opened session. Let's say you want to do a list of operations and in the end flush, then you use withSession. withNewSession is to use a new fresh session. –  Nov 01 '13 at 23:28
  • Can you give me examples when it is recommended to use withNewSession()? – Michael Nov 02 '13 at 01:12
  • @confile The example is in my answer, in the Person class. –  Nov 04 '13 at 02:01
  • Do you use withNewTransaction() only when you delete or create objects? – Michael Nov 04 '13 at 02:29
  • @confile you're confusing `withNewSession` and `withNewTransaction`. Use `withNewSession` in GORM events. I don't have a use case to `withNewTransaction`, but you can use it if you want to handle the status of your transaction like the [example in the docs](http://grails.org/doc/latest/ref/Domain%20Classes/withTransaction.html). –  Nov 04 '13 at 12:59
  • 2
    @confile I think the answer to your question cannot be more lucid and to-the-point than what we have above. Shouldn't related questions be new questions, so that the areas of yours/others excavations is not hidden in comments? – dmahapatro Nov 04 '13 at 14:43