在将Grails项目从1.3.7升级到2.4.0之后,并修复了与新grails版本相关的各种问题之后,我意识到,除非调用save(flush:true),否则对任何对象所做的任何更改都将不再存在。

在Grails 1.3.7中,使用save()保存域实例时的默认行为是由于休眠flushMode => FlushMode.AUTO而使更改自动持久化。在Grails 2.4.0中,这不再是事实。任何 Controller 操作或服务类中的休眠 session 的默认flushMode为FlushMode.MANUAL

在BootStrap中获取sessionFactory.currentSession.flushMode的值和在 Controller 操作中获取FlushMode.AUTO的值时,事情变得更加奇怪。可以通过创建一个新的grails应用程序并将FlushMode.MANUAL放入BootStrap和 Controller 操作(例如index())来验证这一点。

在过去的两天里,我一直在各种论坛中进行搜索,但是没有找到任何合理的解释来解释为什么必须在Grails 2.4.0(甚至是更早的版本)中对此进行更改。我只发现有评论说拥有println "flushMode = $sessionFactory.currentSession.flushMode"是有风险的,因为在修改某些其他数据库后查询数据库时,您可能会遇到过时的对象。

我知道:

在配置中使用FlushMode.MANUAL

  • 您可以对每个save()强制执行flush:true
  • hibernate3和hibernate4中的
  • 默认的flushMode为grails.gorm.autoFlush = true
  • 无法在Config.groovy或DataSource.groovy中设置flushMode。我尝试了所有这些,但没有做任何工作:FlushMode.AUTO

  • 请有人可以对此进行说明吗?

    实际上,我想知道在Grails 2.4.0中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'是否现在是所需的默认值?

    如果是这样:
  • 彼得·莱德布鲁克(Peter Ledbrook)在GRAILS-7180
  • 中的注释“…建议不是我们完全禁用AUTO刷新模式……”
  • 最好的做法是不碰到陈旧对象的问题,尤其是在对域对象进行复杂的操作(其中修改,创建新实例和查询混合在一起)时。

  • 非常感谢
    - 和我

    在阅读Graemes Answer和他的评论后,我试图更好地阐明我正在努力解决的问题,并添加了以下简化的域和 Controller 类,以证明该行为:

    域类消息:

    class Msg {
    
        String  text
    
        static constraints = {
            text nullable:true
        }
    }
    

    和味精 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>')
        }
    }
    


    因此,调用FlushMode.MANUAL的输出是:

    *** flushMode when in controller/save1 = MANUAL
    msg 1 created with text = hallo
    

    在这里我不明白,为什么即使您flushMode为MANUAL,休眠也能持久保存对象。

    当调用http://localhost/appname/msg/save1时,输出为:

    *** flushMode when in controller/save2 = MANUAL
    msg null created with text = hallo
    

    该对象不会持久化,因为休眠不会发出刷新,因此从不调用sql“update ...”命令。

    但是现在看来,不仅flushMode是一个问题,而且无论是否调用hasErrors()都同样如此!我感到更加困惑...

    如果在Grails 1.3.7中执行此示例,则两个保存操作(save1和save2)都将持久保存新创建的msg对象!

    最佳答案

    Grails会在验证之前将刷新模式设置为“手动”,以防止在验证过程中刷新任何更改(这很常见,因为您可能有一个查询现有数据的自定义验证器)。

    参见https://github.com/grails/grails-data-mapping/blob/master/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/HibernateDomainClassValidator.java#L60

    如果存在任何验证错误,它将不会将刷新模式设置回“自动”。这是为了防止无效对象被持久化。

    您看到的是您可能会发生验证错误,尽管您可以强制执行刷新操作,但这并不建议。

    关于hibernate - 刷新模式将grails从AUTO更改为MANUAL,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/24309084/

    10-10 11:18