级联错误将重新保存 grails 删除的对象

Posted

技术标签:

【中文标题】级联错误将重新保存 grails 删除的对象【英文标题】:grails deleted object would be re-saved by cascade error 【发布时间】:2011-04-19 01:15:07 【问题描述】:

我的项目设置如下。我正在尝试删除一个项目,我得到以下信息:

2010-09-29 11:45:22,902 [http-8080-1] ERROR errors.GrailsExceptionResolver  - deleted object would be re-saved by cascade (remove deleted object from associatio
ns): [Project#204]
org.hibernate.ObjectDeletedException: deleted object would be re-saved by cascade (remove deleted object from associations): [Project#204]
        at ProjectController$_closure6.doCall(ProjectController:50)
        at ProjectController$_closure6.doCall(ProjectController)
        at org.jsecurity.web.servlet.JSecurityFilter.doFilterInternal(JSecurityFilter.java:382)
        at org.jsecurity.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:180)
        at java.lang.Thread.run(Thread.java:619)

有什么方法可以让休眠状态告诉我哪个对象具有对将被重新保存的 Project 对象的引用。我的项目设置有什么问题导致此循环异常?

public class Project implements Comparable
  
    static belongsTo = [employee:Employee]

    static hasMany = [roles:Role]
    static constraints = 

    
    static mapping = 
          description type:"text"
          roles lazy:false, cascade:"all,delete-orphan"
          client lazy:false, cascade:"all,delete-orphan"
          employer lazy:false, cascade:"all,delete-orphan"
    



class Employee implements Comparable

    static hasMany = [employeeDesiredSkills:EmployeeDesiredSkill,
                      employeeDesiredTools:EmployeeDesiredTool,
                      employeeAreasOfExpertise:EmployeeAreaOfExpertise,
                      projects:Project,
                      education:Education]


    static mapping = 
           employeeDesiredSkills cascade:"all,delete-orphan", lazy:false
           employeeDesiredTools cascade:"all,delete-orphan", lazy:false
           education cascade:"all,delete-orphan", lazy:false
           projects cascade:"all,delete-orphan", lazy:false
    


public class Role implements Comparable


    static belongsTo = [project:Project]
    static hasMany = [roleSkills:RoleSkill,roleTools:RoleTool]

    static mapping = 
        duties type:"text"
        roleSkills cascade:"all,delete-orphan", lazy:false
        roleTools cascade:"all,delete-orphan", lazy:false
        locationType cascade:"all,delete-orphan", lazy:false

    

    static contraints = 
        endDate(nullable: true)
        roleSkills(nullable: true)
        roleTools(nullable: true)
    


class Employer implements Comparable

   static mapping = 
       type lazy:false, cascade:"all,delete-orphan"
   


class RoleTool implements Comparable    



  static belongsTo = [role:Role, tool:Tool]//not sure this makes sense, but have to leave it or DB breaks
  Tool tool = new Tool(name:"")
    static mapping = 
      tool cascade:"save-update", lazy:false

    


class RoleSkill implements Comparable   


  static belongsTo = [role:Role, skill:Skill]//not sure this makes sense, but have to leave it or DB breaks
    Skill skill = new Skill(name:"")
    static mapping = 
       skill cascade:"save-update", lazy:false

    


class Skill implements Comparable

    static hasMany = [roleSkills:RoleSkill, employeeDesiredSkills:EmployeeDesiredSkill]

    static mapping = 
        roleSkills cascade:"all,delete-orphan", lazy:false
        employeeDesiredSkills cascade:"all,delete-orphan", lazy:false

    



class Tool implements Comparable


    static hasMany = [roleTools:RoleTool, employeeDesiredTools:EmployeeDesiredTool]

    static mapping = 
        roleTools cascade:"all,delete-orphan", lazy:false
        employeeDesiredTools cascade:"all,delete-orphan", lazy:false

    

【问题讨论】:

【参考方案1】:

如果您有级联删除设置,就像您一样,您需要在删除之前从其父级中删除要删除的对象。来自您在 ProcectController 中的堆栈跟踪,大约在第 50 行。

【讨论】:

当您说“要从其父对象中删除的对象”时,这是否意味着对于此示例,我需要从员工中删除项目,或者我是否必须明确地向下删除所有对象被父母删除? 这是我从 ProjectController 中删除的方法: def employee = project.employee;员工.removeFromProjects(项目); project.delete(flush:true)【参考方案2】:

事实上,你完成映射的方式 projects cascade:"all,delete-orphan" 在 Employee 类中。

你只需要这样做:

def employee = project.employee; 
employee.removeFromProjects(project);

该项目也将被删除。 更多详情请参考GORM Gotchas By Peter Led***。 它是一个 3 部分系列,并解释了许多类似的情况

【讨论】:

我终于让它工作了。事实上并没有那么简单。我认为如果项目存储在 SortedSet 中,则存在一个 grails 错误,然后很难进行删除。我必须制作项目的副本,删除我想删除的项目,然后将它们添加回员工以使其正常工作【参考方案3】:

我知道现在很晚了,但有人可能想在这里找到这个: 正如GORM Gotchas By Peter Led*** 中所解释的那样,Hibernate 使用了“dirtyChecking”。

简而言之: Hibernate,因此 Grails 将希望在 Hibernate 会话结束时 save() employee 对象(在您的情况下,在 .delete(flush:true) 调用中),因为它检测到对象已被修改(project 已被压制)。并且employee 必须保持指向project 的链接,导致Hibernate 感觉您将delete()project 重新连接到save()

要解决此问题:

 def employee = project.employee; 
 employee.discard(); 
 project.delete(flush:true);

这告诉 Hibernate 不要在没有你要求的情况下使用 save() employee

【讨论】:

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

休眠删除的对象将被级联重新保存

已删除的对象将通过级联重新保存(从关联中删除已删除的对象)

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

hibernate 多对多操作(级联操作)

为啥 Grails 在域对象保存时不通知我错误?

级联还是不级联? (“对象引用了未保存的瞬态实例”错误)