2013-12-11 42 views
2

保存新创建的域对象(在控制器中)会导致立即刷新休眠会话。 (我增加了睡眠(),以确保它不是一个记录的问题,我是双的mysql-query.log检查,这些调用制成,不仅有“印刷”)保存新的域对象会导致立即刷新

5.times { i -> 
     new Foo(bar: "$i").save() 
     log.error("$i") 
     sleep(1000) 
} 

与Hibernate查询日志启用这导致

2013-12-11 15:26:41,593 [http-bio-8080-exec-6] DEBUG hibernate.SQL - insert into foo (version, bar) values (?, ?) 
| Error 2013-12-11 15:26:41,596 [http-bio-8080-exec-6] ERROR app.HomeController - 0 
2013-12-11 15:26:42,600 [http-bio-8080-exec-6] DEBUG hibernate.SQL - insert into foo (version, bar) values (?, ?) 
| Error 2013-12-11 15:26:42,605 [http-bio-8080-exec-6] ERROR app.HomeController - 1 
2013-12-11 15:26:43,610 [http-bio-8080-exec-6] DEBUG hibernate.SQL - insert into foo (version, bar) values (?, ?) 
| Error 2013-12-11 15:26:43,613 [http-bio-8080-exec-6] ERROR app.HomeController - 2 
2013-12-11 15:26:44,618 [http-bio-8080-exec-6] DEBUG hibernate.SQL - insert into foo (version, bar) values (?, ?) 
| Error 2013-12-11 15:26:44,622 [http-bio-8080-exec-6] ERROR app.HomeController - 3 
2013-12-11 15:26:45,626 [http-bio-8080-exec-6] DEBUG hibernate.SQL - insert into foo (version, bar) values (?, ?) 
| Error 2013-12-11 15:26:45,631 [http-bio-8080-exec-6] ERROR app.HomeController - 4 

看着Grails文档在 http://grails.org/doc/latest/ref/Domain%20Classes/save.html

的保存方法通知实例应该被保存或更新的持久化上下文。除非使用flush参数,否则该对象将不会立即保留:

对于我来说,问题是:文档是错误的还是这是一个错误?

问题(至少对我来说)是完整的会话被刷新,这可能会导致不需要的更改持续存在。

我在grails-2.3.3和grails-2.2.4上重现了这一点,并使用最新的hibernate3和hibernate4插件进行了检查。所有配置组合的行为是相同的,所以我想这是一个误导性的文档,但仍然想要仔细检查。

更新

按照要求由塞尔吉奥这个超级简单的控制导致了上面的输出。

class HomeController { 
def index(){ 
    5.times { i -> 
    new Foo(bar: "$i").save() 
    log.error("$i") 
    sleep(1000) 
    } 
} 
} 
+0

可以共享全控制器代码? –

+0

什么版本的Grails? –

+0

添加了控制器 @BurtBeckwith就像我说过的,我用grails-2.3.3和grails-2.2.4以及最新的hibernate4和hibernate3插件测试过。 – peschenbach

回答

3

你没有看到一个刷新,只是比你期望的更早的SQL。由于您看到的数据库活动比您期望的要早,因此这会分裂一点点,但直到请求结束时才会显式刷新 - 您可以在调试器中或启用日志记录中看到这一点。

你所看到的是Hibernate需要执行插入以检索自动生成的ID。所以它为每个save()调用做了一个明确的插入,但在请求结束时只有一个实际的flush,由OpenSessionInView拦截器触发。

所以文档有点偏离。在新的非持久实例上调用save()将触发数据库插入,但不会刷新。在修改的持久实例上调用save()或在持久化实例上调用delete()将不会触发数据库更新,直到显式刷新或Hibernate检测到它需要(例如,如果您执行查询,则可能会受到未刷新数据的影响。

编辑

下面是一个更大的例子来展示发生了什么。首先,我创建2个Foos并冲洗这些节省。然后我编辑并保存一个,并删除另一个,都没有刷新。我做了5个新实例的相同创建并查看它们的SQL,但没有更新或删除,因为没有刷新。在结束的时候我你是做一个明确的冲洗看到那两个SQL语句:

class HomeController { 

    def index() { 

     def toEdit = new Foo(bar: 'editme').save() 
     def toDelete = new Foo(bar: 'deleteme').save(flush: true) 
     println 'created first 2 and flushed' 

     toEdit.bar += '_edited' 
     toEdit.save() 
     toDelete.delete() 
     println 'edited one, deleted one' 

     5.times { i -> 
     new Foo(bar: "$i").save() 
     println "created foo $i" 
     sleep 1000 
     } 
     println "created 5" 

     println "before explicit flush" 
     Foo.withSession { it.flush() } 
     println "after explicit flush" 
    } 
} 

和这里的输出:

2013-12-11 12:46:20,120 [http-bio-9090-exec-1] DEBUG hibernate.SQL - insert into foo (id, version, bar) values (null, ?, ?) 
2013-12-11 12:46:20,138 [http-bio-9090-exec-1] DEBUG hibernate.SQL - insert into foo (id, version, bar) values (null, ?, ?) 
created first 2 and flushed 
edited one, deleted one 
2013-12-11 12:46:20,188 [http-bio-9090-exec-1] DEBUG hibernate.SQL - insert into foo (id, version, bar) values (null, ?, ?) 
created foo 0 
2013-12-11 12:46:21,197 [http-bio-9090-exec-1] DEBUG hibernate.SQL - insert into foo (id, version, bar) values (null, ?, ?) 
created foo 1 
2013-12-11 12:46:22,202 [http-bio-9090-exec-1] DEBUG hibernate.SQL - insert into foo (id, version, bar) values (null, ?, ?) 
created foo 2 
2013-12-11 12:46:23,211 [http-bio-9090-exec-1] DEBUG hibernate.SQL - insert into foo (id, version, bar) values (null, ?, ?) 
created foo 3 
2013-12-11 12:46:24,219 [http-bio-9090-exec-1] DEBUG hibernate.SQL - insert into foo (id, version, bar) values (null, ?, ?) 
created foo 4 
created 5 
before explicit flush 
2013-12-11 12:46:25,282 [http-bio-9090-exec-1] DEBUG hibernate.SQL - update foo set version=?, bar=? where id=? and version=? 
2013-12-11 12:46:25,284 [http-bio-9090-exec-1] DEBUG hibernate.SQL - delete from foo where id=? and version=? 
after explicit flush 
+0

burt,这是一个很好的答案,谢谢。 – peschenbach

+0

Hey Burt!感谢你的回答。我不同意这个文件只是一点点。 @peschenbach从来没有抱怨会议被刷新到早些时候,但关于对象被持续,虽然他们不会。我们只需更新那里的文档,不是吗? – fluxon