I have the project as set-up below. I am trying to delete a project, and I get the following:
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)
Is there any way to get hibernate to tell me which object has the reference back to the Project object that would be re-saved. What is wrong with my project set up that is causing this circular exception?
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开发者_Python百科-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
}
}
Infact, the way you have done the mapping
projects cascade:"all,delete-orphan"
in the Employee class.
You'll just need to do:
def employee = project.employee;
employee.removeFromProjects(project);
And the project will be deleted as well. For more details, refer to GORM Gotchas By Peter Ledbrook. Its a 3 part series and explains many similar situations
I know it is late but someone may like to find this here: What happens is that Hibernate uses 'dirtyChecking', as explained in GORM Gotchas By Peter Ledbrook.
To make things short:
Hibernate, and so Grails will want to save()
the employee
object at the end of the Hibernate session (in your case at the .delete(flush:true)
call) because it detects that the object has been modified (a project
has been suppressed). And the employee
must have kept a link toward the project
, causing Hibernate to feel you will delete()
the project
to save()
it back again.
To workaround this:
def employee = project.employee;
employee.discard();
project.delete(flush:true);
This tell Hibernate not to save()
the employee
without you asking for it.
if you have cascade for delete setup, like you do, you need to remove the object-to-delete from its parent before deleting it. From your stacktrace in ProcectController around line 50.
精彩评论