【问题标题】:Grails 3.3: Is only the first save() persisted?Grails 3.3:只有第一个 save() 持久化吗?
【发布时间】:2018-07-04 19:30:18
【问题描述】:

是否只保留了域对象实例上的第一个 save()?

环境:Grails 3.3.5、GORM 6.1.9 我相信、PostgreSQL 9.5、JDK 1.8.0_171、Ubuntu 16.04。

我的应用程序根据来自多个文本文件的输入创建 Recital(域对象)实例。这是一个数据库加载,所以一切都发生在一个控制器调用中,调用一个服务方法。一笔交易。

服务方法解析输入流以寻找演奏会。当它找到一个时,它会尝试 findBy 方法(演奏会编号)。如果有给定编号的 Recital,它会从输入更新它并执行 save()。否则,它会从输入创建一个新实例并执行 save()。 failOnError 无处不在。独奏会不属于任何东西,没有级联问题。

程序逻辑无法判断修改是否是实例的最后一次更新。因此,每次更改后都会有一个 save() 。但这不起作用。看来你只能 save() 一次。

在数据库中找到的最终结果是只有第一个 save() 被持久化。在调试正在运行的程序时,我可以验证实例在内存中是否已完全更新。

如果这是正确的,文档应该说:save 方法通知持久性上下文应该保存或更新实例的当前状态。此后(在同一事务中)的任何和所有修改都将被忽略。 除非使用 flush 参数,否则对象不会立即持久化...

附: save() 文档将“flush: true”解释为刷新持久性上下文。这对新手来说几乎没有解释价值。一些“冲洗”同义词是:清洗、擦除、删除、清除、清扫、擦除。数据库人员可能会将其视为 ROLLBACK 而不是 COMMIT。解释当然是 Hibernate 术语。如果 Grails doco 大部分是独立的,那就太好了。 (同一文档中的附带问题。)

【问题讨论】:

  • 你试过.save(flush:true)吗?那是为了“现在”保存,不能对文档说什么:)
  • 是的,没有区别。然而,新的见解,见下文。

标签: grails grails-orm grails-3.3


【解决方案1】:

在太多人浪费时间之前,这里有一些新的见解。

Recital 域恰好有一个嵌入式组件。我的应用中的更新仅影响嵌入式组件的成员。

我已经验证,对于同一个实例的三个特定更新,成员在内存中被正确更新。但是,在三个更新中的每一个之后, recital.isDirty() 都会返回 false,同样, recital.isDirty('body') 其中 body 是嵌入的组件。

我的结论是更新嵌入式组件不一定会在实例上设置脏标志。所以它没有被保存。忘记原始问题中提出的理论。似乎有一个 Grails/GORM 错误。

我现在的解决方法是用 executeUpdate 替换更新。一团糟,但我在这上面花了太多时间,必须继续努力。

编辑:不是错误。 GORM 现在需要使用 @DirtyCheck 注释嵌入的类以进行脏检查。结案。

【讨论】:

    【解决方案2】:

    如果我不在交易中,我只能看到所描述的行为,无论如何这都是不好的做法。所以我怀疑你不是在交易中,或者不是一直在交易中。 你确定所有涉及的方法都用@Transactional注解吗?

    flush: true 的意思不是提交,而是执行对数据库的插入/更新,所以 Tuomas 的建议应该有效,但如果我是对的,你仍然在事务之外,如果发生异常,您有部分保存的数据。 仅当您将所有使用 @Transactional 注释的方法保留时,才会放置提交,但如果存在未捕获的 RunTimeException,您将获得回滚。

    在同一事务中考虑这一点:

    Recital.save(); Racital.count() -> 0

    Recital.save(flush: true); Racital.count() -> 1

    如果您查看 SQL 日志,您可以看到只保存了新对象的第一个 .save(),所有更新都会保留到您离开事务,这可能会节省开销。我猜,因为你没有在事务中,最后一次更新永远不会执行。

    顺便说一句,IMO grails 文档是我所知道的最好的 OSS 项目之一。如果您稍后查看它,您可能会看到有关陷阱的提示,但它不会在所有地方重复它们。

    【讨论】:

    • 感谢您的努力,但这肯定会发生在 @Transactional 服务中。新见解,也许我会回答我自己的问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-27
    • 2014-10-20
    • 1970-01-01
    • 2012-11-14
    • 2015-12-11
    相关资源
    最近更新 更多