刷新模式在Grails中从AUTO更改为MANUAL

And*_*zer 7 grails hibernate flush save

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

使用Grails 1.3.7时,使用域实例保存时的默认行为save()是,由于hibernate flushMode =>,更改会自动保留FlushMode.AUTO.在Grails 2.4.0中,这不再适用.任何控制器操作或服务类内的hibernate会话的默认flushMode是FlushMode.MANUAL.

sessionFactory.currentSession.flushMode在BootStrap中检索时,事情变得更加奇怪,它FlushMode.AUTO在控制器操作中具有值,并且具有值FlushMode.MANUAL.这可以通过创建新的grails应用程序并放入println "flushMode = $sessionFactory.currentSession.flushMode"BootStrap和控制器操作(例如index())来验证.

我在过去的两天里一直在搜索所有类型的论坛,但没有找到任何合理的解释,为什么必须在Grails 2.4.0(或者甚至是早期版本)中更改它.我只发现评论说它有风险,FlushMode.MANUAL因为在修改了其他一些文件后,你可能会遇到陈旧的对象.

我知道:

  • grails.gorm.autoFlush = true在配置你可以强制刷新:真实每次保存()
  • 在hibernate3和hibernate4中默认的flushMode是 FlushMode.AUTO
  • 它不可能在Config.groovy或DataSource.groovy中设置flushMode.我尝试了所有这些,没有做任何工作: 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'

请问有人可以点一点吗?

实际上我想知道Grails 2.4.0 FlushMode.MANUAL现在是否是理想的默认值?

如果是这样:

  • 什么是评论"...提案并不是我们完全禁用了自动冲洗模式..."作者:Peter Ledbrook在GRAILS-7180
  • 没有遇到陈旧对象问题的最佳做法是什么,特别是在对域对象进行复杂操作时,修改,创建新实例和查询都是混合的.

非常感谢 - 安迪


在阅读Graemes Answer和他的评论后,我试图更好地阐明我正在努力解决的问题,并添加了以下简化的域和控制器类来演示这种行为:

域类消息:

class Msg {

    String  text

    static constraints = {
        text nullable:true
    }
}
Run Code Online (Sandbox Code Playgroud)

和msg控制器:

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>')
    }
}
Run Code Online (Sandbox Code Playgroud)


所以调用http://localhost/appname/msg/save1输出是:

*** flushMode when in controller/save1 = MANUAL
msg 1 created with text = hallo
Run Code Online (Sandbox Code Playgroud)

在这里我不明白,为什么hibernate持久化对象,即使你的flushMode是MANUAL.

当调用http://localhost/appname/msg/save2输出时:

*** flushMode when in controller/save2 = MANUAL
msg null created with text = hallo
Run Code Online (Sandbox Code Playgroud)

该对象不会被持久化,因为hibernate不会发出flush,因此永远不会调用sql"update ..."命令.

但现在似乎不仅flushMode是一个问题,而且如果一个人调用hasErrors()或者不是!我更困惑的是......

如果您在Grails 1.3.7中执行此示例,则保存操作(save1和save2)会保留新创建的msg对象!

Gra*_*her 9

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

如果存在任何验证错误,则不会将刷新模式设置回AUTO.这是为了防止无效对象被持久化.

您所看到的是您可能发生了验证错误,虽然您可以强制刷新,但这是不可取的.