【问题标题】:SpringMVC + hibernate @ManyToMany, controller losing collection during updateSpringMVC +休眠@ManyToMany,控制器在更新期间丢失收集
【发布时间】:2018-01-19 14:00:28
【问题描述】:

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

当我尝试更新Employee 并通过JSP 表单添加另一个Project 时,控制器使Set<Project>empty。所以,当我提交表单时,休眠而不是向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();

}

employee-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&lt;Projects&gt;,我知道这个集合丢失了saveOrUpdateEmployee 方法中的所有值。我不知道我在哪里犯了错误。感谢您的帮助。

【问题讨论】:

  • 可能会有所帮助。 stackoverflow.com/questions/3738934/…
  • cascadeType 在这里应该不会造成任何问题。可能是saveOrUpdateEmployee,该项目未保存在数据库中,因此无法添加,这可能会导致它设置一个新项目。
  • 我同意级联似乎没问题。可能在将 Employee 传递给saveOrUpdateEmployee 方法期间丢失了对Set&lt;Projects&gt; 的引用。

标签: java hibernate spring-mvc


【解决方案1】:

我找到了问题的可能原因。当我提交更新表单时,Spring 创建了我的Employee.class 的新实例,这意味着Set&lt;Project&gt; 成为一个新的空集。由于我传入了我的 Employee 的 &lt;form:hidden path="id"&gt; id,因此休眠会覆盖我在 DB 中的所有值,包括我的项目集合。

现在我想知道如何防止这种行为? &lt;form:hidden path="projects"&gt; 不起作用。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-30
    • 2021-12-07
    • 1970-01-01
    • 2013-10-24
    • 2011-07-13
    • 2017-02-07
    相关资源
    最近更新 更多