Hi ,
I am trying to model a One To Many relationship using a Link Table (aka Join Table) - and I am struggling with a Cascade delete that goes horribly wrong. I am using JPA with Hibernate Annotations
Entity classes are a) Project.java , b) Employee.java . A project can have many employees in it . Hence a Project will have a List<Employee> employees
// mapping for this in Project.java is as follows
@OneToMany(fetch=FetchType.LAZY,cascade=CascadeType.ALL) @Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN) @JoinTable(name="PROJECT_EMPLOYEE_LINK", joinColumns=@JoinColumn(name="PROJECT_ID"), inverseJoinColumns=@JoinColumn(name="EMPLOYEE_ID") ) public List<Employee> getEmployees() { return employees; }
The link table is a PROJECT_EMPLOYEE_LINK with ONLY 2 cols in it viz PROJECT_ID, EMPLOYEE_ID
Employee.java is a normal Entity class, with Id, firstName,lastName,designation properties public class Employee implements Serializable { @Id private Long id ; private String firstName; private String lastName; private String designation; } Note: No reference in employee class to the parent entity , i.e. Project
In my test class I have the following method :
public void testSaveEmployeeWithProject() throws Exception { Project project = new Project(); project.setDescription("xproject"); Employee emp1 = new Employee("employee1"); Employee emp2 = new Employee("employee2") ; Employee emp3 = new Employee("employee3") ; List<Employee> list = new ArrayList<Employee>(); list.add(emp1); list.add(emp2); list.add(emp3); project.setEmployees(list); // this will save it PROJECT, EMPLOYEE ( one or more rows ) , and EMPLOYEE_PROJECT_LINK ( employee and project ID ) employeeDAO.saveProjectDetails(project); }
The save works fine ... When I run the above test , one row in PROJECT table, 3 rows in employee table , and 3 rows in the link table ( PROJECT_EMPLOYEE_LINK ) get saved.
The problem I have is when I TRY to delete a Project - What I would expected to see is that
a. The correct Project ID is deleted in the db.
b. All the corresponding rows for the particular PROJECT_ID are removed from the PROJECT_EMPLOYEE_LINK Table . How can a link between Project and Employee exist, when there is no Project itself ? c. Employee is left untouched... As they are separte entities that exist on their own. Possibly other entities like Payroll, HR etc could be referring to the Employee . Also this is the VERY Reason , why Employee has been modelled separately without having any FK references to other Entities.
What happens is that rows in the Project, Employee, as well as PROJECT_EMPLOYEE_LINK all get deleted .
Adding the @Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN) ensures that the rows in the PROJECT_EMPLOYEE_LINK table get deleted . This is bcos I read somewhere that JPA on its own does nt support the equivalent of the Hibernate all delete orphan , and hence this custom Hibernate annotation is required.
Table structure is as follows
EMPLOYEE --------- ID FIRST_NAME LAST_NAME DESIGNATION
PROJECT --------- ID PROJECT_NAME DESCRIPTION
PROJECT_EMPLOYEE_LINK -------------------------- PROJECT_ID references PROJECT.ID EMPLOYEE_ID references EMPLOYEE.ID
I am using JPA 1 , Hibernate 3.2.3.ga,Hibernate Annotations 3.3.1.ga,Hibernate Entity Manager 3.3.2.ga, javax-persistance 1.0, Spring 2.5.6
Any help will be greatly appreciated
Many thanks
Kasi
_________________ ----------------- Kasi Subramaniam -----------------
|