Scott Jordan
Scott Jordan

Reputation: 122

Grails requires explicit flush to actually persist changes

I'm trying to persist a one-to-many relationship in Grails with the following domain classes. A user should have many tasks (and a task should have a reference to its user).

User.groovy

package helloworld

class User {
    String name
    String password
    Date   register_date

    static hasMany = [tasks: Task]
    static mapping = {
        tasks cascade: "all-delete-orphan"
    } 
    static constraints = {
    }
}   

Task.groovy

package helloworld

class Task {
    String description
    Date due
    Boolean deleteFinished
    Boolean finished

    static belongsTo = [owner: User]
    static constraints = {
    } 
}   

TodoController.groovy (the problem?)

...
def persist() {
    User u = User.get(session["user_id"])
    Boolean df = params["deleteFinished"] != null
    Task t = new Task(description: params["description"], due: params["due"], deleteFinished: df, finished: false)
    u.addToTasks(t)
    u.save(flush: true) //problem point
    redirect(action: 'index')
}

...

So according to all documentation I've read the hibernate session is supposed to be flushed and closed at the end of every request, but that doesn't seem to be the case here. u.save(flush: true) works as it should, persisting any changes or added children (Task t), but when I use u.save() any changes made to u as well as Task t don't get persisted after the end of the request. What's even more bizarre, if I move the code to a Grails service with transaction encapsulated methods, u.save() works. I've checked everything I can think of. My domain objects are attached, they are valid, they detect that they're dirty when they change. Can anyone help me figure out this mystery?

Upvotes: 0

Views: 643

Answers (1)

ascu
ascu

Reputation: 1139

Controllers don't have transactions enabled by default. Moving the code to a service (they are transactional by default) or annotating your method as transactional should solve your problem.

import grails.transaction.Transactional

    @Transactional
    def persist() {
        User u = User.get(session["user_id"])
        Boolean df = params["deleteFinished"] != null
        Task t = new Task(description: params["description"], due: params["due"], deleteFinished: df, finished: false)
        u.addToTasks(t)
        u.save()
        redirect(action: 'index')
    }

Upvotes: -1

Related Questions