【问题标题】:EntityManager merge is not working while updating OneToMany Side更新 OneToMany Side 时 EntityManager 合并不起作用
【发布时间】:2016-06-07 11:14:08
【问题描述】:

我有两个具有双向 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 中没有更新员工部门,我在这里做错了什么。或者级联是否只在父级到子级之间起作用?

谢谢。

【问题讨论】:

    标签: java entity jpa-2.0


    【解决方案1】:

    我认为您无需担心此处的合并,您只需要更新关系的双方即可。从您的查询返回的员工对象已被管理/附加。

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

    所以你可以添加:

        // ...
        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
    }
    

    【讨论】:

    • 这不是我要的,但感谢您的回复
    • 由于我不确定您的要求有何不同,因此我编辑了答案以更清楚地解释我在说什么。
    猜你喜欢
    • 2013-04-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-05
    相关资源
    最近更新 更多