更新OneToMany Side时,EntityManager合并不起作用

时间:2016-06-07 11:14:09

标签: java entity jpa-2.0

我有两个双向 OneToMany 关系的实体。例如

Employee.java

package com.jpademo.entities;

import java.io.Serializable;
import javax.persistence.*;

/**
 * Entity implementation class for Entity: Employee
 *
 */
@Entity
@Table(name = "Employee")
@SequenceGenerator(name = "Emp_Id_Gen", sequenceName = "EMP_ID_SEQ_GEN", allocationSize = 1)
public class Employee implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(generator = "Emp_Id_Gen")
    private Integer employeeId;

    private String Name;

    @ManyToOne(cascade = { CascadeType.ALL })
    private Department department;

    public Integer getEmployeeId() {
        return employeeId;
    }

    public void setEmployeeId(Integer employeeId) {
        this.employeeId = employeeId;
    }

    public String getName() {
        return Name;
    }

    public void setName(String name) {
        Name = name;
    }

    public Department getDepartment() {
        return department;
    }

    public void setDepartment(Department department) {
        this.department = department;
    }

}

Department.java

package com.jpademo.entities;

import java.io.Serializable;
import java.util.List;

import javax.persistence.*;

/**
 * Entity implementation class for Entity: Department
 *
 */
@Entity
@Table(name = "Department")
@SequenceGenerator(name = "Dept_Id_Gen", sequenceName = "DEPT_ID_SEQ_GEN", allocationSize = 1)
public class Department implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(generator = "Dept_Id_Gen")
    private Integer deptId;

    private String deptName;
    @OneToMany(mappedBy = "department", cascade = { CascadeType.MERGE,
            CascadeType.PERSIST })
    private List<Employee> employees;

    public Integer getDeptId() {
        return deptId;
    }

    public void setDeptId(Integer deptId) {
        this.deptId = deptId;
    }

    public String getDeptName() {
        return deptName;
    }

    public void setDeptName(String deptName) {
        this.deptName = deptName;
    }

    public List<Employee> getEmployees() {
        return employees;
    }

    public void setEmployees(List<Employee> employees) {
        this.employees = employees;
    }

}

EmployeeDAO.java

package com.jpademo.dao;

import java.util.Arrays;
import java.util.List;

import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;

import com.jpademo.entities.Department;
import com.jpademo.entities.Employee;

@Stateless(name = "employeeDAO")
@LocalBean
public class EmployeeDAO {

    @PersistenceContext(unitName = "JPA2Pratice")
    private EntityManager em;

    public void saveEmployee() {
        Employee emp = new Employee();
        emp.setName("Mukesh Saini");
        Department dept = new Department();
        dept.setDeptName("Physics");
        emp.setDepartment(dept);
        em.persist(emp);
    }

    public void addEmployeeToDepartment() {
        TypedQuery<Department> departmentQuery = em
                .createQuery(
                        "SELECT dept FROM Department dept WHERE dept.deptId = :departmentId",
                        Department.class);
        departmentQuery.setParameter("departmentId", 1);
        Department dept = departmentQuery.getSingleResult();
        // Employee already in department
        List<Employee> currentEmpinDept = dept.getEmployees();

        // Employee that need to be add in department
        TypedQuery<Employee> employeeQuery = em.createQuery(
                "SELECT emp FROM Employee emp WHERE emp.employeeId IN :empIds",
                Employee.class);
        employeeQuery.setParameter("empIds", Arrays.asList(2, 3));
        List<Employee> employees = employeeQuery.getResultList();
        currentEmpinDept.addAll(employees);
        dept.setEmployees(currentEmpinDept);
        em.merge(dept); // this does not update employee department

    }



}

的persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
    xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
    <persistence-unit name="JPA2Pratice">
        <jta-data-source>jdbc/MySQLDataSource</jta-data-source>
        <properties>
            <property name="eclipselink.ddl-generation" value="create-tables" />
            <property name="eclipselink.logging.level.sql" value="FINE" />
            <property name="eclipselink.logging.parameters" value="true" />
        </properties>
    </persistence-unit>
</persistence>

在EmployeeDAO em.merge(dept)中的方法 addEmployeeToDepartment 没有更新员工部门,我在这里做错了什么。或者 cascade是否仅在Parent之间工作?

感谢。

1 个答案:

答案 0 :(得分:0)

我认为你不必担心合并,你只需要更新关系的两面。从您的查询返回的员工对象已经被管理/附加。

但根据herehere,仅仅在父部门对象上设置新的Employee对象列表是不够的。您还必须更新每个子Employee上对Department的引用。

所以你可以添加:

    // ...
    List<Employee> employees = employeeQuery.getResultList();

    // NEW:  Update owning side     
    for (Employee e : employees) {
        e.setDepartment(dept);
    }
    currentEmpinDept.addAll(employees);
    dept.setEmployees(currentEmpinDept);

    //em.merge(dept);   - DON'T THINK THIS IS NEEDED
}