After updating my Grails project from 1.3.7 to 2.4.0 and after fixing various problems associated with the new version of grails, I realized that none of the changes made to any object will be saved (in general), except if save(flush:true) .
With Grails 1.3.7, the default behavior when saving a domain instance using save() is that the changes are automatically saved due to the flushMode => FlushMode.AUTO hibernation mode. In Grails 2.4.0, this is no longer the case. By default, a hush session flushMode is inside any controller action or class of service FlushMode.MANUAL .
Things get even sessionFactory.currentSession.flushMode when retrieving sessionFactory.currentSession.flushMode in BootStrap, where it has the value FlushMode.AUTO and in the controller action, where it has the value FlushMode.MANUAL . This can be verified by creating a new grails application and placing println "flushMode = $sessionFactory.currentSession.flushMode" in the BootStrap and in the controller action (e.g. index ()).
I searched all forums for the past 2 days and did not find a reasonable explanation why this should have been changed in Grails 2.4.0 (or, perhaps, even in earlier versions). I just found comments saying that it is risky to have FlushMode.MANUAL , because you may run into obsolete objects when querying db after some others have been changed.
I know that:
- with
grails.gorm.autoFlush = true in the configuration, you can force a flash: true for each save () - in hibernate3 and hibernate4 default flushMode there is
FlushMode.AUTO - Cannot set flushMode to Config.groovy or DataSource.groovy. I tried all this and did nothing:
hibernate.flush.mode = 'auto' hibernate.flushMode = 'auto' hibernate.session.flush.mode = 'auto' hibernate.session.flushMode = 'auto' dataSource.hibernate.flush.mode = 'auto' dataSource.hibernate.flushMode = 'auto' dataSource.hibernate.session.flush.mode = 'auto' dataSource.hibernate.session.flushMode = 'auto' dataSource.flush.mode = 'auto' dataSource.flushMode = 'auto' dataSource.session.flush.mode = 'auto' dataSource.session.flushMode = 'auto'
Please, can anyone refresh this a bit?
In fact, I would like to know if Grails 2.4.0 has FlushMode.MANUAL in the default one?
And if so:
- What is there with the comment "... The suggestion is not that we completely turned off AUTO flush mode ..." Peter Ledbrook in GRAILS-7180
- What is the best practice so as not to run into problems with obsolete objects, especially with complex manipulations with domain objects, where the change, creating new instances and query are all mixed.
Thanks a lot - Andy
After reading Graemes Answer and his comments, I tried to better explain what I'm struggling with, and added the following simplified domain and controller classes that demonstrate this behavior:
Msg Domain Class:
class Msg { String text static constraints = { text nullable:true } }
and msg controller:
class MsgController { def sessionFactory def index = { def out = ["*** flushMode when in controller/index = \ $sessionFactory.currentSession.flushMode"] Msg.list().each { out << "$it.id: text=$it.text" } render out.join('<br>') } // this save does persist the new msg object, // even if flushMode = MANUAL def save1 = { def out = ["*** flushMode when in controller/save = \ $sessionFactory.currentSession.flushMode"] def msg = new Msg(text:'hallo') if (!msg.save()) { out << "msg has errors! " + msg.errors } out << "msg $msg.id created with text = $msg.text" render out.join('<br>') } // this save does NOT persist the new msg object, even if its valid // (difference is calling hasErrors() def save2 = { def out = ["*** flushMode when in controller/save = \ $sessionFactory.currentSession.flushMode"] def msg = new Msg(text:'hallo') if (msg.hasErrors() && !msg.save()) { out << "msg has errors! " + msg.errors } out << "msg $msg.id created with text = $msg.text" render out.join('<br>') } }
Thus, the call http://localhost/appname/msg/save1 is output as follows:
*** flushMode when in controller/save1 = MANUAL msg 1 created with text = hallo
Here I donβt understand why hibernate continues the object, even you flushMode - MANUAL.
And when calling http://localhost/appname/msg/save2 output is:
*** flushMode when in controller/save2 = MANUAL msg null created with text = hallo
The object is not saved because hibernation does not create a flash, therefore, it never calls the sql command "update ...".
But now it seems that the problem is not only with flushMode, but with the hasErrors () call or not! I'm still puzzled yet ...
If you do this example in Grails 1.3.7, both save the actions (save1 and save2), save the newly created msg object!