将我的Grails项目从1.3.7升级到2.4.0并在修复了与新grails版本相关的各种问题之后,我意识到对任何对象所做的任何更改都不会再存在(根本不存在),除非{ {1}}被调用。
使用Grails 1.3.7时,使用save(flush:true)
保存域实例时的默认行为是,由于hibernate flushMode =>,更改会自动保留。 save()
。在Grails 2.4.0中,这不再适用。任何控制器操作或服务类内的hibernate会话的默认flushMode是FlushMode.AUTO
。
在BootStrap中检索FlushMode.MANUAL
时,事情变得更加奇怪,它的值为sessionFactory.currentSession.flushMode
,在控制器操作中,它的值为FlushMode.AUTO
。这可以通过创建一个新的grails应用程序并将FlushMode.MANUAL
放在BootStrap和控制器操作(例如index())中来验证。
过去两天我一直在搜索所有类型的论坛,但没有找到任何合理的解释,为什么必须在Grails 2.4.0中更改(或者甚至在早期版本中)。我只发现评论说println "flushMode = $sessionFactory.currentSession.flushMode"
存在风险,因为在修改其他数据库后查询数据库时可能会遇到过时的对象。
我知道:
FlushMode.MANUAL
grails.gorm.autoFlush = true
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'
现在是否是所需的默认值?
如果是这样的话:
非常感谢 - 安迪
在阅读Graemes Answer和他的评论后,我试图更好地阐明我正在努力解决的问题,并添加了以下简化的域和控制器类来证明这种行为:
域类消息:
FlushMode.MANUAL
和msg控制器:
class Msg {
String text
static constraints = {
text nullable:true
}
}
所以调用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
在这里我不明白,为什么hibernate会持久化对象,即使flushMode是MANUAL。
当调用*** flushMode when in controller/save1 = MANUAL
msg 1 created with text = hallo
时输出为:
http://localhost/appname/msg/save2
该对象不会被持久化,因为hibernate不会发出flush,因此永远不会调用sql“update ...”命令。
但现在似乎不仅flushMode是一个问题,而且如果一个人调用hasErrors()或者不是!我更困惑了......
如果您在Grails 1.3.7中执行此示例,则保存操作(save1和save2)会保留新创建的msg对象!
答案 0 :(得分:9)
Grails会在验证之前将刷新模式设置为手动,以防止在验证期间刷新任何更改(这可能非常常见,因为您可能有一个查询现有数据的自定义验证程序)。
如果存在任何验证错误,则不会将刷新模式设置回AUTO。这是为了防止无效对象被持久化。
您所看到的是您可能发生了验证错误,虽然您可以强制进行同花,但这并不可取。