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

tik*_*kka 4 grails grails-orm

看起来这已经被问过很多次了,我已经研究了其中的几个,包括Peter Ledbrook的“ GORM Gotchas(第 2 部分) ”,但在我的情况下似乎仍然无法弄清楚。我有一个user其中有很多projects,一个project属于一个user。然后有一个skill其中有许多projects与它相关联,但project不属于skill。当我尝试project从 a 中删除 a 时,出现user该错误。域类如下:

    打包 grailstuts

    类用户{
        字符串名称

        静态约束 = { name(nullable: true) }

        静态映射 = { 项目级联:“all-delete-orphan”}

        静态 hasMany = [ 项目:项目 ]
    }

    打包 grailstuts

    类项目{
        字符串标题

        静态约束 = { 标题(可为空:真)}

        静态属于 = [ 用户:用户 ]
    }

    打包 grailstuts

    类技能{
        字符串名称

        静态约束 = { name(nullable: true) }

        静态映射 = { 项目级联:“all-delete-orphan”}

        静态 hasMany = [ 项目:项目 ]
    }

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

    打包 grailstuts

    导入 spock.lang.*

    class 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:...块,当我尝试删除projectuser,即当错误似乎发生。错误看起来像这样......

    | 正在运行 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.adding 和删除项目(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

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

rxn*_*n1d 5

all-delete-orphan- 仅适用于一对多关联,并表示 当从关联中删除子项时,应自动将其删除 。当父项删除时,子项也会被删除。因此,当您打电话时,foundUser.removeFromProjects(foundProject1)您正在尝试删除foundProject1对象,但无法从数据库中删除它,因为Skill实体仍然引用此项目。如何修复:

  • 第一种方法:Remove projects cascade: "all-delete-orphan"fromUser防止在调用时删除项目user.removeFromProjects(...)
  • 第二种方法:调用skill.removeFromProjects(...)保存项目,这样项目将被删除