Thorsten Viel
Thorsten Viel

Reputation: 1199

save(flush: true) is not flushing the session

I was creating a new grails app with several domain classes and controllers. All my controllers have working methods for save(), update() and list(), e.g.

def update(Long id, Long version) {
    def crawlerConfigInstance = CrawlerConfig.get(id)
    if (!crawlerConfigInstance) {
        flash.message = message(code: 'default.not.found.message', args: [message(code: 'crawlerConfig.label', default: 'CrawlerConfig'), id])
        redirect(action: "list")
        return
    }

    if (version != null) {
        if (crawlerConfigInstance.version > version) {
            crawlerConfigInstance.errors.rejectValue("version", "default.optimistic.locking.failure",
                    [message(code: 'crawlerConfig.label', default: 'CrawlerConfig')] as Object[],
                    "Another user has updated this CrawlerConfig while you were editing")
            render(view: "edit", model: [crawlerConfigInstance: crawlerConfigInstance])
            return
        }
    }

    crawlerConfigInstance.properties = params

    if (!crawlerConfigInstance.save(flush: true)) {
        render(view: "edit", model: [crawlerConfigInstance: crawlerConfigInstance])
        return
    }

    flash.message = message(code: 'default.updated.message', args: [message(code: 'crawlerConfig.label', default: 'CrawlerConfig'), crawlerConfigInstance.id])
    redirect(action: "show", id: crawlerConfigInstance.id)
}

which is actually an autogenerated / scaffolded method by IDE

However, now I was adding an additional controller method which should run through a list of domain objects and update them accordingly. Getting the list, changing the attributes and validation is successfull.

save(flush:true) doesn't throw any errors and returns the updated domain object, as expected. However, checking the hibernate SQL statements, all I see is SELECTS, no update. In fact, if I directly call a delete() on the domain object after the save(), I get a concurrent transaction exception on the domain object.

My controller method looks like

def doSomething() {     

    def results = CrawlerConfig.findAll(bQ)

    results.each { crawlerConfigInstance ->

            crawlerConfigInstance.needsReview = true

            if (!crawlerConfigInstance.save(flush:  true)) {
                render(view: "show", model: [crawlerConfigInstance: crawlerConfigInstance])
                return
            }
    }

    redirect(action: "list")
}

Pretty straightforward. If I check for the dirty fields, needsReview is marked as dirty before the save(). save() updates the version on the object.

I currently still use h2:mem as database.

For me it looks like the transaction is not finished. But I don't get why or how I can get it to finish.

Thx in advance

EDIT after POST from Ondrej

created a Service (which gets injected and called fine)

package lizard

import org.springframework.transaction.annotation.Transactional

@Transactional class CrawlerConfigPersistenceService {

static transactional = true

def checkRequirementsForCrawlerConfigList(String query) {

    def results = CrawlerConfig.findAll(query)

    results.each { crawlerConfigInstance ->

        crawlerConfigInstance.needsReview = true

        if (!crawlerConfigInstance.save(flush: true)) {
            println crawlerConfigInstance.errors.getAllErrors()
            return
        }

    }
}
}

But this results in exactly the same behaviour, everything looks OK, except that there is no update statement raised by hibernate

Upvotes: 0

Views: 2873

Answers (1)

Ondrej Kvasnovsky
Ondrej Kvasnovsky

Reputation: 4643

Move your methods for save(), update() and list() from Controllers to Services. Before doing it, have a look here and read the Services chapter: http://grails.org/doc/latest/guide/services.html

Upvotes: 0

Related Questions