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

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

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

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

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

我知道:

>在配置中使用grails.gorm.autoFlush = true可以强制刷新:true为每个save()
>在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
    }
}

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

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

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

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

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

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

该对象不会被持久化,因为hibernate不会发出flush,因此永远不会调用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

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

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

本站公众号
   欢迎关注本站公众号,获取更多程序园信息
开发小院