Grails3.3:是否只有第一个save()被持久化?

Grails3.3:是否只有第一个save()被持久化?,grails,gorm,grails-3.3,Grails,Gorm,Grails 3.3,是否仅保留域对象实例上的第一个save() 环境:Grails 3.3.5,我相信GORM 6.1.9,PostgreSQL 9.5,JDK 1.8.0_171,Ubuntu 16.04 我的应用程序根据大量文本文件的输入创建背诵(域对象)实例。这是一个数据库负载,所以一切都发生在一个控制器调用中,调用一个服务方法。一笔交易 服务方法解析输入流以查找叙述。当它找到一个时,它会尝试一个findBy方法(引言被编号)。如果有一个具有给定数字的背诵,它会从输入中更新它并保存()。否则,它将从输入创建一

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

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

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

服务方法解析输入流以查找叙述。当它找到一个时,它会尝试一个findBy方法(引言被编号)。如果有一个具有给定数字的背诵,它会从输入中更新它并保存()。否则,它将从输入创建一个新实例并保存()。失败的人到处都是好办法。独奏会不属于任何东西,没有级联问题

程序逻辑无法判断修改是否是实例的最后一次更新。因此,每次更改后都会有一个save()。但这是行不通的。似乎只能保存()一次

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

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


另外,save()文档将“flush:true”解释为刷新持久性上下文。这对新手来说没有什么解释价值。一些“冲洗”同义词是:清洗、擦除、删除、清除、清扫、擦拭。数据库人员可能会将其作为回滚而不是提交。当然,解释是Hibernate术语。如果Grails文档基本上是独立的,那就太好了。(同一文档中的附带问题。)

我只能在不参与事务的情况下看到所描述的行为,这是一种糟糕的做法。所以我怀疑你不是在交易中,或者不是一直在交易中。 您确定所有涉及的方法都用@Transactional注释了吗

flush:true
的意思不是提交,而是对数据库执行insert/update,因此Tuomas的建议应该有效,但是如果我是对的,您仍然在事务之外,如果发生异常,您就保存了部分数据。 只有将所有方法都保留为@Transactional注释时,才会进行提交,但如果存在未捕获的RunTimeException,则会得到回滚

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

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

readal.save(刷新:true);Racital.count()
->1

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


顺便说一句,grails文档是我所知道的最好的OSS项目之一。如果你以后再复习,你可能会看到一些关于陷阱的提示,但它不会到处重复。

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

事实上,背诵域有一个嵌入式组件。我的应用程序中的更新仅影响嵌入组件的成员

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

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

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


编辑:不是错误。GORM现在要求使用
@DirtyCheck
注释嵌入式类,以便进行脏检查。案例关闭。

您是否尝试过使用
.save(flush:true)
?这是为了保存“立即”,不能对文档做任何说明:)是的,没有区别。不过,新的见解,请参见下文。感谢您的努力,但使用@Transactional服务肯定会发生这种情况。新的见解,也许我会回答我自己的问题。