Search code examples
javahibernatejpaormeclipselink

Merging a managed entity on the @ManyToOne side


Given below a one-to-many relationship from Department to Employee.

Department (parent) :

@OneToMany(mappedBy = "department", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private List<Employee> employeeList = new ArrayList<Employee>(0);

Employee (child) :

@JoinColumn(name = "department_id", referencedColumnName = "department_id")
@ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH, CascadeType.DETACH})
private Department department;

Merging a managed entity (child) like the following (using CMT in EJB),

Employee employee = entityManager.find(Employee.class, 1L);
employee.setDepartment(department); // department is supplied by a client.
employee.setEmployeeName("xyz");
entityManager.merge(employee);

does not update the corresponding employee row in the database table. It happens only when CascadeType.MERGE is removed from the child @ManyToOne relationship in Employee.

Why doesn't the row in the table get updated? What is the sole purpose of CascadeType.MERGE regarding this example?

I am currently using EclipseLink 2.6.0 having JPA 2.1.


Solution

  • Cascading should always propagate from a Parent to a Child and not the other way around.

    In your case, you need to remove the Cascade from the child-side:

    @JoinColumn(name = "department_id", referencedColumnName = "department_id")
    @ManyToOne(fetch = FetchType.LAZY)
    private Department department;
    

    and make sure you set both sides of the association:

    Employee employee = entityManager.find(Employee.class, 1L);
    employee.setDepartment(department);
    employee.setEmployeeName("xyz");
    department.getEmployeeList().add(employee);
    entityManager.merge(department);