2010-09-29 9 views
6

Tengo el proyecto como se describe a continuación. Estoy tratando de eliminar un proyecto, y me sale el siguiente:grails el objeto eliminado se volvería a guardar por error de cascada

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) 

¿Hay alguna manera de hibernación para dígame qué objeto tiene la referencia al objeto de proyectos que se vuelva a guardar. ¿Qué hay de malo en la configuración de mi proyecto que está causando esta excepción circular?

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 

    } 
} 

Respuesta

9

De hecho, la forma en que lo ha hecho el mapeo projects cascade:"all,delete-orphan" en la clase Empleado.

Usted sólo tiene que hacer:

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

Y el proyecto se eliminará también. Para obtener más información, consulte GORM Gotchas By Peter Ledbrook. Sus una serie de 3 partes y explica muchas situaciones similares

+2

Finalmente lo puse en funcionamiento. De hecho, no es tan simple. Creo que hay un error de grial si los proyectos se almacenan en SortedSet, entonces tiene dificultades para eliminarlos. Tuve que hacer una copia de los proyectos, eliminar el que quería eliminar y volver a agregarlo al empleado para que funcione. – Derek

0

si tiene en cascada para la configuración de eliminación, como lo hace, hay que desmontar el objeto que va a eliminar de su padre antes de eliminarlo. Desde su StackTrace en ProcectController alrededor de la línea 50.

+0

cuando dice "objeto para eliminar de su padre" significa que para este examen necesito eliminar Project del empleado, o tengo que ir explícitamente al árbol eliminando todos los objetos que están a punto de ser eliminados de su padres? – Derek

+0

He aquí cómo estaba eliminando de ProjectController: def employee = project.employee; \t employee.removeFromProjects (proyecto); project.delete (flush: true) – Derek

5

Sé que es tarde, pero alguien puede tener gusto de encontrar esta aquí: Lo que pasa es que Hibernate utiliza 'dirtyChecking', como se explica en GORM Gotchas By Peter Ledbrook.

Para hacer las cosas a corto: Hibernate, y así Griales querrá save() el objeto employee al final de la sesión de Hibernate (en su caso en la llamada .delete(flush:true)) ya que detecta que el objeto ha sido modificado (un project ha sido suprimido). Y el employee debe haber mantenido un enlace hacia project, haciendo que Hibernate sienta que va a delete()project a save() de nuevo.

Para solucionar esto:

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

Este decirle a Hibernate que no save() la employee sin que pedirlo.

Cuestiones relacionadas