2010-09-29 4 views
6

Ho il progetto come impostato di seguito. Sto cercando di eliminare un progetto, e ottengo il seguente:sarebbe stato nuovamente salvato dall'errore a cascata

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) 

C'è un modo per ottenere in letargo per dirmi quale oggetto ha il riferimento di nuovo all'oggetto progetto che sarebbe ri-salvato. Cosa c'è di sbagliato nel mio progetto che sta causando questa eccezione circolare?

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 

    } 
} 

risposta

9

Infatti, il modo in cui avete fatto la mappatura projects cascade:"all,delete-orphan" nella classe Employee.

Avrete solo bisogno di fare:

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

E il progetto verrà eliminato pure. Per ulteriori dettagli, fare riferimento a GORM Gotchas By Peter Ledbrook. Le sue una serie in 3 parti e spiega molte situazioni simili

+2

Finalmente ho funzionato. Non è così semplice. Penso che ci sia un bug Grails se i progetti sono memorizzati in SortedSet, quindi ha difficoltà a farlo rimuovere. Dovevo fare una copia dei progetti, rimuovere quello che volevo eliminare, quindi aggiungerli nuovamente al dipendente per farlo funzionare – Derek

0

se avete a cascata per la configurazione di cancellazione, come si fa, è necessario rimuovere l'oggetto da eliminare dal suo genitore prima di eliminarlo. Dal vostro stacktrace in ProcectController intorno alla linea 50.

+0

quando si dice "oggetto da eliminare dal suo genitore" vuol dire che per questo esame ho bisogno di rimuovere Project dal dipendente, o devo andare esplicitamente nell'albero rimuovendo tutti gli oggetti che stanno per essere cancellati dal loro i genitori? – Derek

+0

Ecco come stavo facendo la rimozione da ProjectController: def employee = project.employee; \t employee.removeFromProjects (progetto); project.delete (flush: true) – Derek

5

So che è tardi, ma qualcuno hanno la possibilità di trovare questo qui: quello che succede è che Hibernate usa 'dirtyChecking', come spiegato nel GORM Gotchas By Peter Ledbrook.

Per rendere le cose a breve: Hibernate, e così Grails vorrà save() l'oggetto employee al termine della sessione di Hibernate (nel tuo caso alla chiamata .delete(flush:true)) perché esso rileva che l'oggetto è stato modificato (un project è stato soppresso). E lo employee deve aver mantenuto un collegamento verso lo project, facendo in modo che Hibernate ritenga che lo sarà delete() lo project a save() indietro.

per risolvere questo:

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

Questo dirà Hibernate non save() il employee senza chiedere per essa.