Hibernate grails中的刷新模式从自动更改为手动
在将我的Grails项目从1.3.7升级到2.4.0并解决了与新Grails版本相关的各种问题之后,我意识到对任何对象所做的更改都不会再被持久化(根本),除非调用了Hibernate grails中的刷新模式从自动更改为手动,hibernate,grails,save,flush,Hibernate,Grails,Save,Flush,在将我的Grails项目从1.3.7升级到2.4.0并解决了与新Grails版本相关的各种问题之后,我意识到对任何对象所做的更改都不会再被持久化(根本),除非调用了save(flush:true) 对于Grails 1.3.7,使用save()保存域实例时的默认行为是,由于hibernate flushMode=>flushMode.AUTO,更改会自动持久化。在Grails2.4.0中,这不再是事实。任何控制器操作或服务类中hibernate会话的默认刷新模式为flushMode.MANUAL
save(flush:true)
对于Grails 1.3.7,使用save()
保存域实例时的默认行为是,由于hibernate flushMode=>flushMode.AUTO
,更改会自动持久化。在Grails2.4.0中,这不再是事实。任何控制器操作或服务类中hibernate会话的默认刷新模式为flushMode.MANUAL
在BootStrap中检索sessionFactory.currentSession.flushMode
时,情况变得更加奇怪,它的值为flushMode.AUTO
,在控制器操作中,它的值为flushMode.MANUAL
。这可以通过创建一个新的grails应用程序并将println“flushMode=$sessionFactory.currentSession.flushMode”
放入引导和控制器操作(例如index())来验证
在过去的两天里,我一直在搜索各种论坛,没有找到任何合理的解释来解释为什么必须在Grails2.4.0(甚至可能在更早的版本中)中对此进行更改。我只发现一些评论说,使用FlushMode.MANUAL
有点冒险,因为在修改了其他对象之后,在查询数据库时可能会遇到过时的对象
我知道:
- 在配置中使用
可以强制刷新:true到每个save()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'
FlushMode.MANUAL
中的默认值是否是现在所需的
若有:
- 彼得·莱德布鲁克(Peter Ledbrook)在年发表的评论“…建议不是我们完全禁用自动刷新模式…”是什么意思
- 最好的做法是避免遇到过时对象的问题,特别是在对域对象执行复杂操作时,其中修改、创建新实例和查询都是混合的
在阅读Graemes的答案和他的评论后,我试图更好地澄清我正在努力解决的问题,并添加了以下简化的域和控制器类,以演示该行为: 域类消息:
class Msg{
字符串文本
静态约束={
文本可为空:true
}
}
以及msg控制器:
class MsgController{
def会话工厂
def索引={
def out=[“***在控制器/索引中时刷新模式=\
$sessionFactory.currentSession.flushMode“]
Msg.list()。每个{outGrails将在验证之前将刷新模式设置为手动,以防止在验证期间刷新任何更改(这可能非常常见,因为您可能有一个查询现有数据的自定义验证器)
看
如果存在任何验证错误,它将不会将刷新模式设置回自动。这是为了防止无效对象被持久化
您看到的是,您可能出现了验证错误,尽管您可以强制刷新,但这是不可取的。感谢您的解释。这是有意义的。但是,为什么Grails在控制器操作中切换到手动,即使没有保存域对象(根本不用)?我编写了一个只有一个控制器的小型Grails应用程序,没有域类来验证这一点。在控制器索引操作中,我只放了一个LOCprintln“flushMode=$sessionFactory.currentSession.flushMode”
对于读取操作,Grails使用只读事务。只读事务使用手动刷新模式。读取操作使用只读事务的原因是因为它提高了性能,因为Hibernate不需要脏检只读对象。这可能就是您看到的。请参阅更新域和c的原始问题OnController示例您的第二个示例毫无意义,因为执行if(msg.hasrerrors()&&&!msg.save())
意味着永远不会调用save()
,因为hasrerrors()
将返回false
对不起,我的打字错误!应该是if(msg.hasrerrors()| | msg.save())
然后这两个操作都会保留msg对象,而上面的整个示例毫无意义!我必须检查有问题的代码,并尝试提取它以使问题可见。。。