grails 插入数据库而不保存,为什么?

发布于 2024-12-17 12:11:23 字数 299 浏览 3 评论 0原文

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

我创建一个像这样的对象:

User a = new User()
a.setName("test")
a.save()

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

a.setActive(true)

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

非常感谢,

马可

I found something strange in Grails.

I create an object like:

User a = new User()
a.setName("test")
a.save()

after that I call a Method e.g. setActive like:

a.setActive(true)

and DON'T call save() but it is saved in the database. I don't know why?! I think this is dangerous. Any suggestions on this?

Thanks a lot,

Marco

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

压抑⊿情绪 2024-12-24 12:11:23

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

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

为了解决这个问题,如果您只想临时修改现有实例(例如在 GSP 中渲染),但不希望自动保留更改,则可以使用 read() 方法加载现有实例。

这在您的情况下不起作用,因为您没有获得旧实例,而是正在创建它。在您的情况下,只需在保存后调用 a.discard() 即可将其与 Hibernate 会话断开连接,并且当刷新发生时 Hibernate 将不会有任何内容可推送。

Grails registers an "OpenSessionInView" interceptor that opens a Hibernate session at the beginning of each request, and flushes and closes it after it's finished. This is primarily there for lazy-loaded collections. If there wasn't an open session, after loading the instance it would immediately become disconnected, so trying to access a collection would throw an exception. By keeping the session active, the collections can be resolved.

By default Hibernate automatically pushes changes in persistent instances during a flush, so since the OSIV interceptor flushes at the end of the request, any "dirty" instances like your User instance will have their changes pushed to the database.

To get around this, you can use the read() method to load an existing instance if you only want to modify it temporarily, e.g. for rendering in the GSP, but don't want changes auto-persisted.

This won't work in your case since you're not getting an old instance, you're creating it. In your case just call a.discard() after saving and that will disconnect it from the Hibernate session, and Hibernate won't have anything to push when the flush happens.

忘羡 2024-12-24 12:11:23

执行服务方法后(在事务 = true 的情况下)grails 会保存域/持久对象的所有更改并刷新休眠会话。
控制器操作中的重定向行为相同。
要回滚更改 - 抛出 RuntimeException。

After execution of service methods (in case of transactional = true) grails save all changes with domain/persist objects and flush hibernate session.
The same behaviour of Redirect in controller action.
To rollback changes - throw RuntimeException.

━╋う一瞬間旳綻放 2024-12-24 12:11:23

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

如果您通过调用 .save() 来表明您希望某个对象持久化,Hibernate 会假定您还希望保存对该对象的任何后续更改。如果您不希望保留该更新,我认为调用 a.setActive(true) 没有意义。

Because Hibernate automatically saves all pending updates to persistent objects before it closes the session. This is just how Hibernate works.

If you indicate that you want an object to be persistent by calling .save() on it, Hibernate assumes that you also want any subsequent changes to that object to be saved. I don't see the point in calling a.setActive(true) if you don't want that update to be persisted.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文