Grails/GORM 中的错误:已删除的对象将被级联重新保存

Posted

技术标签:

【中文标题】Grails/GORM 中的错误:已删除的对象将被级联重新保存【英文标题】:Error in Grails/GORM: deleted object would be re-saved by cascade 【发布时间】:2013-11-26 14:22:24 【问题描述】:

看起来这个问题已经被问过很多次了,我已经研究了其中的几个,包括 Peter Led*** 的“GORM Gotchas (Part 2)”,但在我的情况下似乎仍然无法弄清楚。我有一个user,其中有很多projects,而project 属于user。然后有一个skill,它有许多与之关联的projects,但project 不属于skill。当我尝试从user 中删除project 时,我得到了那个错误。领域类如下:

打包 grailstuts 类用户 字符串名称 静态约束 = name(nullable: true) 静态映射 = 项目级联:“所有删除孤儿” 静态 hasMany = [项目:项目] 打包 grailstuts 类项目 字符串标题 静态约束 = title(nullable: true) 静态 belongsTo = [用户:用户] 打包 grailstuts 类技能 字符串名称 静态约束 = name(nullable: true) 静态映射 = 项目级联:“所有删除孤儿” 静态 hasMany = [项目:项目]

当我如下运行集成测试时,包含foundUser.removeFromProjects(foundProject1) 的部分似乎有问题。

打包 grailstuts 导入 spock.lang.* 类 SkillIntegrationSpec 扩展规范 void "添加和删除项目"() 给定:“一个用户,以及添加到该用户的项目” def user = new User().save(failOnError: true) def project1 = new Project(title: "java, groovy") def project2 = new Project(title: "java, scala") user.addToProjects(project1) user.addToProjects(project2) 何时:“项目也添加到技能条目” def java = new Skill(name: 'java').save(failOnError: true) java.addToProjects(project1) java.addToProjects(project2) def groovy = new Skill(name: 'groovy').save(failOnError: true) groovy.addToProjects(project1) def scala = new Skill(name: 'scala').save(failOnError: true) scala.addToProjects(project2) 然后:“每个技能条目都有其对应的项目” Skill.findByName("java").projects.size() == 2 Skill.findByName("groovy").projects.size() == 1 Skill.findByName("scala").projects.size() == 1 何时:“某些项目已从数据库中删除” def foundUser = User.get(user.id) def foundProject1 = Project.findByTitle("java, groovy") foundUser.removeFromProjects(foundProject1) 然后:“被删除的项目也反映在技能条目中” Skill.findByName("java").projects.size() == 1 Skill.findByName("groovy").projects.size() == 0 Skill.findByName("scala").projects.size() == 1

上述测试中的第一个given:... when:... then:... 块验证正常。在第二个when:... 块中,当我尝试从user 中删除project 时,似乎出现了错误。错误看起来像这样......

|正在运行 1 个集成测试... 1 of 1 |失败:添加和删除项目(grailstuts.SkillIntegrationSpec) | org.springframework.dao.InvalidDataAccessApiUsageException:已删除的对象将被级联重新保存(从关联中删除已删除的对象):[grailstuts.Project#2];嵌套异常是 org.hibernate.ObjectDeletedException:已删除的对象将被级联重新保存(从关联中删除已删除的对象):[grailstuts.Project#2] 在 org.grails.datastore.gorm.GormStaticApi.methodMissing_closure2(GormStaticApi.groovy:102) 在 grailstuts.SkillIntegrationSpec.添加和删除项目(SkillIntegrationSpec.groovy:34) 原因:org.hibernate.ObjectDeletedException:已删除的对象将被级联重新保存(从关联中删除已删除的对象):[grailstuts.Project#2] ... 2 更多 |完成 1 次集成测试,1 次在 0m 0s 内失败 |测试失败 - 在 C:\Grails\grailstuts\target\test-reports 中查看报告

我正在使用:

Grails 版本:2.3.1 Groovy 版本:2.1.8 JVM版本:1.7.0_45

已经花了很多时间寻找一些解决方案,但还没有运气。任何帮助将不胜感激。谢谢!

【问题讨论】:

【参考方案1】:

all-delete-orphan - 仅适用于一对多关联和 表示 当一个孩子从一个关联中移除时,它应该被自动删除 .当 父母是。因此,当您调用 foundUser.removeFromProjects(foundProject1) 时,您正在尝试删除 foundProject1 对象,但无法从数据库中删除它,因为 Skill 实体仍然引用此项目。如何解决:

第一种方法:从User 中删除projects cascade: "all-delete-orphan" 以防止在调用user.removeFromProjects(...) 时删除项目 第二种方法:使用保存项目调用skill.removeFromProjects(...),以便删除该项目

【讨论】:

谢谢@araxn1d,您的解释简单易懂,而且简洁优雅——第一次尝试就奏效了。这两种方法都工作得很好。就我而言,当我删除project 时,我还希望将其从数据库中删除,因此适用第二种方法。但是感谢您对这两种方式的解释,它提供了一个完整的画面,并且在这种情况下整个事情如何运作更加清晰。从您的解释来看,我似乎也不需要Skill 类中的static mapping = projects cascade: "all-delete-orphan" ,果然我不需要那个!谢谢! 很高兴能帮到你。祝你的 grails 应用程序开发顺利 =) 谢谢,@araxn1d。看起来在我之前的许多尝试中,我尝试过类似于第二种方法的东西。但是,它不起作用,因为我试图删除多个项目,并且我试图首先从他们各自的用户中删除所有项目,然后试图从关联中删除项目,但这不起作用。当我以另一种方式进行时,即首先从关联中删除,然后再从父母中删除,它会起作用。所以顺序似乎很重要,而且现在很有意义。非常感谢您提供清晰简洁的解释!

以上是关于Grails/GORM 中的错误:已删除的对象将被级联重新保存的主要内容,如果未能解决你的问题,请参考以下文章

如何覆盖 Grails GORM 中关系的级联删除?

GRAILS / GORM:动态多重连接

在 Grails (GORM) 中处理并发修改,同时避免过时对象异常

Grails GORM 查询以匹配多个关联对象

Grails + GORM:GORM 中默认的 equals() 实现是啥?

在 Grails/GORM 中定义默认排序顺序