Hibernate Cascading Delete Not working as expected

BuffaloBuffalo picture BuffaloBuffalo · Apr 15, 2011 · Viewed 12.4k times · Source

I am using hibernate 3 and attempting to delete a record in the database, and the delete is not working as I would expect. The schema hibernate is working against (in pseudocode):

create table Employer(
    employer_id number(12) primary key,
    employer_name varchar2(50)
);

create table Employee(
    employee_id number(12) primary key,
    employee_name varchar2(50),
    employer_id number(12) foreign key references employer.employer_id not null
);

create table Employee_Roles(
    role_id number(12) primary key,
    employee_id number(12) foreign key references employee.employee_id not null,
    role varchar2(50)
);

My hibernate class mappings look something like:

@Entity
public class Employer{

    @Id
    @Column(name = "EMPLOYER_ID")
    private long id;

    @Column
    private String name;


    @OneToMany(targetEntity = Employee.class, fetch = FetchType.EAGER)
    @JoinColumn(name = "employer_id")
    @Cascade(CascadeType.ALL)
    private Set<Employee> employees;
}

@Entity
public class Employee{

    @ManyToOne(targetEntity = Employer.class)
    @JoinColumn(name = "employer_id")
    @Cascade(value = CascadeType.SAVE_UPDATE)
    private Employer employer;

    @OneToMany(targetEntity = EmployeeRole.class, fetch = FetchType.EAGER)
    @JoinColumn(name = "employee_id")
    @Cascade(CascadeType.ALL)
    private Set<Employee> employees;
}

@Entity
public class EmployeeRole{

    @ManyToOne(targetEntity = Employee.class)
    @JoinColumn(name = "employee_id")
    @Cascade(value = CascadeType.SAVE_UPDATE)
    private Employee employee;
}

Now with this configuration I am calling:

getCurrentSession().delete(someEmployerEntity);

What is occurring is:

Hibernate: update EMPLOYEE set EMPLOYEE_ID=null where EMPLOYEE_ID=?
Hibernate: update EMPLOYEE_ROLE set employee_id=null where employee_id==?
[2011-04-15 15:59:53,487] JDBCExceptionReporter WARN  - SQL Error: -10, SQLState: 23502
[2011-04-15 15:59:53,487] JDBCExceptionReporter ERROR - integrity constraint violation: NOT NULL check constraint; SYS_CT_10058 table: EMPLOYEE_ROLE

and an exception being raised. What I am expecting as a result of the session.remove(..) call is the employer record to be deleted, as well as all employee records associated with the employer and all EmployeeRole records associated with the deleted employee records. Is this a correct assumption? Or am I misunderstanding a key concept here?

Answer

Mr. Nobody picture Mr. Nobody · Apr 16, 2011

Cascade all-delete-orphan should solve your problem. However, it is part of Hibernate and not EJB standard. If you want to do it and do not be trapped in your vendors' solution, I would suggest you to have a look to this article.

Good luck!

EDIT: following your suggestions I added the 'mappedBy' attributes to the @OneToMany annotations which seems to be the annotations way of using inverse="true" for specifying the owning relationships. The relevant changed sections of the relationships look like:

public class Employee{

    @OneToMany(targetEntity = EmployeeRole.class, mappedBy="employee", fetch = FetchType.EAGER,  cascadeType=CascadeType.ALL)
    private Set<EmployeeRole> employeeRoles;
}


public class Employer{

    @OneToMany(targetEntity = Employee.class, mappedBy="employer", fetch = FetchType.EAGER, cascadeType=CascadeType.ALL)
    private Set<Employee> employees;
}