简体   繁体   中英

why does save() not save the data and save(flush: true) is required?

RaceRegistration domain has embedded raceParticipant and raceParticipant has a field bibNumber which is Integer.

I have a method for nulling out all bibNumbers of registrations but without flush:true in save, the nulling out of bibs dont work. The bibs are not set to null.

def nullifyBibNumbers(Long id){

        ...

        def regss = RaceRegistration.createCriteria().list(){

            eq('compositeEvent', event)

        }



        regss.each{ r ->

            r.raceParticipant.bibNumber = null
            r.save()
        }


        render "Bibs resetted!"


    }

If i add flush:true then the bibs are set to null.

    regss.each{ r ->

        r.raceParticipant.bibNumber = null
        r.save(flush: true)
    }

I am wondering why you need flush in order for the value to be set to null? I am guessing the problem is with regard to how i am obtain the registration list using createCriteria(). I appreciate any help in this dilemma i am facing. Thanks!

As you probably figured out, save(flush: true) forces Hibernate to write any pending changes to the database. Without the explicit flush, you're relying on a Hibernate transaction to automatically flush when the transaction commits.

The reason only an explicit flush is working for you is because you're not calling save() within a transaction.

The cleanest fix is to create a Grails service, put nullifyBibNumbers() in it, and make the service transactional . That will cause nullifyBibNumbers() to get wrapped in a transaction so that you can use save() without an explicit flush.

If nullifyBibNumbers() is already in a service, you can add @Transactional to the service class, just keep in mind that it will make all methods (perhaps only the public ones?) transactional. Having said that, you can use @NotTransactional on a method to disable transactions.

The value is null in your domain object. But you are talking about null in the database, I guess? It shouldn't matter. This is basic ORM. As a developer you don't care about when the flush is done. Typically this would be at the end of a transaction. The ORM will then flush all of the changes for that transaction at once. It works on what is called the first-level cache during the transaction, and tries to avoid going to the db until it is explicitly requested ( flush:true ) or required (end of transaction).

Without the using of

save(flush: true) 

The object will not be persisted immediately.

You can follow the documentation link and see the following information:

The save method informs the persistence context that an instance should be saved or updated. The object will not be persisted immediately unless the flush argument is used.

Related to the null issue you are facing make sure that the following condition are met.

The save method returns null if validation failed and the instance was not persisted, or the instance itself if successful.

You do not need the flush in order for the value to be set to null. The flush only care of a quick update of the database.

ok i fixed this problem using HQL instead of domain saves. Still i would appreciate why save() didnt work and save(flush:true) saved the data. Thanks!

RaceRegistration.executeUpdate("update RaceRegistration set raceParticipant.bibNumber = null where compositeEvent.id = :ev", [ev: id])

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM