保存新创建的域对象(在 Controller 中)会导致休眠 session 立即刷新。 (我添加了 sleep() 以确保这不是日志记录问题,并且我仔细检查了 mysql-query.log 是否进行了这些调用,而不仅仅是“打印”)
5.times { i ->
new Foo(bar: "$i").save()
log.error("$i")
sleep(1000)
}
启用休眠查询日志后,这会导致
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
The save method informs the persistence context that an instance should be saved or updated. The object will not be persisted immediately unless the flush argument is used:
我的问题是:文档是错误的还是这是一个错误?
问题(至少对我来说)是整个 session 被刷新,这可能会导致不需要的更改被持久化。
我在 grails-2.3.3 和 grails-2.2.4 上重现了这个,并检查了最新的 hibernate3 和 hibernate4 插件。所有配置组合的行为都是相同的,所以我想这是一个误导性的文档,但我仍然想仔细检查。
更新
按照 sergio 的要求,这个 super 简单的 Controller 会产生上面的输出。
class HomeController {
def index(){
5.times { i ->
new Foo(bar: "$i").save()
log.error("$i")
sleep(1000)
}
}
}
最佳答案
您没有看到刷新,只是看到比您预期更早的 SQL。这有点令人烦恼,因为您看到的数据库事件比您预期的要早,但直到请求结束才显式刷新 - 您可以在调试器中或启用日志记录时看到这一点。
您看到的是 Hibernate 需要执行插入才能检索自动生成的 id。因此,它为每个 save()
调用执行显式插入,但在请求结束时只有一次真正的刷新,由 OpenSessionInView 拦截器触发。
所以文档有点偏离。在新的非持久实例上调用 save()
将触发数据库插入,但不会触发刷新。在已修改的持久实例上调用 save()
或在持久实例上调用 delete()
不会触发数据库更新,除非显式刷新,或者 Hibernate 检测到需要更新,例如如果您执行查询,因为这可能会受到未刷新数据的影响。
编辑
这里有一个更大的例子来展示正在发生的事情。首先,我创建 2 个 Foos 并刷新这些保存。然后我编辑并保存一个并删除另一个,两者都没有刷新。我以同样的方式创建了 5 个新实例并查看了它们的 SQL,但没有更新或删除的 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
关于grails - 保存新的域对象会导致立即刷新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20522320/