grails插入到DB而不保存,为什么?

时间:2011-11-23 10:22:47

标签: grails save

我在Grails中发现了一些奇怪的东西。

我创建了一个像:

的对象
User a = new User()
a.setName("test")
a.save()

之后我调用一个方法,例如setActive喜欢:

a.setActive(true)

不要调用save()但它保存在数据库中。我不知道为什么?!我觉得这很危险。对此有何建议?

非常感谢,

3 个答案:

答案 0 :(得分:6)

Grails注册了一个“OpenSessionInView”拦截器,它在每个请求开始时打开一个Hibernate会话,并在完成后刷新并关闭它。这主要适用于延迟加载的集合。如果没有打开的会话,在加载实例后它会立即断开连接,因此尝试访问集合会引发异常。通过保持会话处于活动状态,可以解析集合。

默认情况下,Hibernate会在刷新期间自动推送持久化实例中的更改,因此OSIV拦截器会在请求结束时刷新,因此任何“脏”实例(如User实例)都会将其更改推送到数据库。

要解决此问题,如果您只想暂时修改现有实例,则可以使用read()方法加载现有实例,例如用于在GSP中呈现,但不希望更改自动保留。

这不适用于你的情况,因为你没有得到一个旧实例,你正在创建它。在你的情况下,只需在保存后调用a.discard(),这将使它与Hibernate会话断开连接,并且当刷新发生时,Hibernate将无法推送任何内容。

答案 1 :(得分:3)

执行服务方法后(在transactional = true的情况下)grails使用domain / persist对象保存所有更改并刷新休眠会话。
控制器操作中Redirect的相同行为 要回滚更改 - 抛出RuntimeException。

答案 2 :(得分:2)

因为Hibernate在关闭会话之前会自动将所有挂起的更新保存到持久对象。这就是Hibernate的工作原理。

如果您通过调用.save()来指示您希望对象是持久的,则Hibernate会假定您还希望保存对该对象的任何后续更改。如果您不希望保留更新,我不会在调用a.setActive(true)时看到这一点。