【发布时间】:2015-01-24 04:06:09
【问题描述】:
我需要根据控制器请求重置 GORM 夹具数据 (H2)。所以我创建了以下控制器...
def dataSource
FixtureLoader fixtureLoader
def index() {
Sql sql = new Sql(dataSource)
sql.execute("DROP ALL OBJECTS DELETE FILES")
sql.close()
fixtureLoader.load('f1','f2','f3')
}
我希望这会清除数据库,但是,我仍然收到以下错误
[org.codehaus.groovy.grails.web.errors.GrailsExceptionResolver] 处理请求时发生 NonUniqueObjectException:[GET] 具有相同标识符值的不同对象已经存在 与会话相关联:[*]。堆栈跟踪如下: org.hibernate.NonUniqueObjectException: 一个不同的对象 相同的标识符值已与会话关联:[*]
另一个奇怪的事情是,如果我进入 dbconsole 并使用“DROP ALL OBJECTS DELETE FILES”命令将所有内容吹走,当我进入控制器时,我会遇到同样的错误。尽管我可以确认它们已从数据库中删除。
更新
所以我尝试了一些东西......
1.) 'DROP ALL OBJECTS DELETE FILES' 似乎在 dbconsole 中按预期工作。但是代码
Sql sql = new Sql(dataSource)
sql.execute("DROP ALL OBJECTS DELETE FILES")
sql.close()
似乎没有同样的效果。
2.) 我添加了以下几行
def sessionFactory
...
sql.close()
sessionFactory.currentSession.flush() //This one
fixtureLoader.load('f1','f2','f3')
然后我去数据库控制台删除(因为 SQL 似乎失败了),然后运行。但是,当我再次运行该函数时,我仍然可以看到固定装置。
【问题讨论】:
-
听起来好像休眠会话/缓存没有被刷新/清除,因此即使您更改了数据存储也认为存在重复。您可能很幸运在测试环境中禁用了休眠缓存。
-
这就是我认为 close 所做的,我也尝试了 sql.execute("DROP ALL OBJECTS DELETE FILES")
-
请看我的更新,我没有正确清除缓存吗?
-
您在这里遗漏了一个基本的难题。即使您执行一条 SQL 语句来“清除”所有数据,Hibernate 仍然存在于您的典型 Grails 应用程序中,并且默认情况下它有自己的缓存,独立于您的数据库。当您在不通过 Hibernate 的情况下更改数据库时,您正在规避 Hibernate 管理缓存的能力,因此最终会出现这种情况,虽然数据不存在,但 Hibernate 仍然认为它存在。考虑清除 Hibernate cahce,或禁用它(如果这对您的应用有意义),或使用 Hibernate 进行核对。
-
session.flush()不会做任何事情,因为您没有使用 Hibernate 会话来影响您的数据库。所以,不,那是不正确的。
标签: grails grails-orm