SpringMVC + hibernate @ManyToMany,控制器在更新期间丢失收集

时间:2018-01-19 14:00:29

标签: java hibernate spring-mvc

我有两个实体Employee.classProject.class,它们之间有@ManyToMany个关系。

当我尝试更新Employee并通过JSP表单向其添加另一个Project时,控制器会使Set<Project>为空。因此,当我提交表单时,休眠而不是向Set<Project>添加另一个项目,这样做:

 Hibernate: update employee set ....(IT'S OK)
 Hibernate: update project set...(IT'S OK)
 Hibernate: delete from employee_project where employee_id=?(IT'S NOT OK)

Employee.class

@Entity
@Table(name="employee")
public class Employee{

//other fields 

@ManyToMany(fetch= FetchType.EAGER, 
        cascade=CascadeType.ALL) 
@JoinTable(name="employee_project",joinColumns=@JoinColumn(name="employee_id"),
     inverseJoinColumns=@JoinColumn(name="project_id"))
private Set<Project> projects = new HashSet<>();

 public Set<Project> getProjects() {
    return projects;
}

public void setProjects(Set<Project> projects) {
    this.projects = projects;
}

Project.class

@Entity
@Table(name="project")
public class Project {

@ManyToMany(fetch= FetchType.EAGER, mappedBy="projects")
private Set<Employee> employees = new HashSet<>();

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

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

EmployeeController.class

@GetMapping("/employeeForm")
public String showEmployeeForm(Model theModel) {

    Employee theEmployee = new Employee();
    theModel.addAttribute("employee", theEmployee);
    theModel.addAttribute("projects", projectService.getProjectsIdMap());

    return "employee-form";
}

@GetMapping("/employee/{id}/updateEmployee")
public String updateEmployee(@PathVariable("id") Long employeeId, Model theModel) {
    //HERE MY Set<Project> IS FULL OF PROJECTS
    theModel.addAttribute("employee", employeeService.getEmployee(employeeId)); 

    theModel.addAttribute("projects", projectService.getProjectsIdMap());

    return "employee-form";
}
@PostMapping("/saveEmployee")
public String saveOrUpdateEmployee(@ModelAttribute("employee") 
   Employee theEmployee) {

 //HERE MY Set<Project> IS EMPTY
        theEmployee.getProjects()
           .add(projectService
             .getProject(theEmployee.getProjectId()));

        employeeService.saveEmployee(theEmployee);
        return "redirect:/employees/employee/" + theEmployee.getId();

}

雇员-form.jsp

 <form:form action="/employee_manager/employees/saveEmployee"
        modelAttribute="employee" method="POST">

        <form:hidden path="id"/>

            <form:select path="projectId">
                <form:options items="${projects}" />
            </form:select>

            <input type="submit" value="Save" />
        </div>
    </form:form>  

Employee.Repository(DAO)

 public void saveEmployee(Employee employee) {
    Session session = sessionFactory.getCurrentSession();

    session.saveOrUpdate(employee);
}

Employee.Service

 @Transactional
public void saveEmployee(Employee employee) {
    employeeRepository.saveEmployee(employee);

}

数据库结构: enter image description here

看起来某处spring设置了一个新集合,而不是添加到现有集合中。

我正在尝试调试应用流程并按照Set<Projects>进行操作,我知道此集合会使saveOrUpdateEmployee方法中的所有值都失效。我无法弄清楚我在哪里弄错了。谢谢你的帮助。

1 个答案:

答案 0 :(得分:0)

我找到了可能导致问题的原因。当我提交更新表单时,Spring会创建我的Employee.class的新实例,这意味着Set<Project>成为新的空集。由于我传递了员工的<form:hidden path="id"> id,因此hibernate会覆盖数据库中的所有值,包括我的项目集合。

现在我想知道如何防止这种行为? <form:hidden path="projects">无效。

使用@InitBinder - &gt; binder.setDisallowedFields({"projects"})也不起作用。