0

I got two entities Employee.class and Project.class with @ManyToMany relation between them.

When I'm trying to update Employee and add another Project to it via JSP form, controller makes Set<Project>empty. So, when I submit the form, hibernate instead of adding another project to Set<Project>, makes this:

 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);

}

DB structure: enter image description here

It looks like somewhere spring set a new collection instead of adding to existing one.

I was trying to debug the app flow and follow Set<Projects> and I know that this collection losess all values in saveOrUpdateEmployee method. I can't figure out where did I make mistake. Thanks for your help.

F.Burian
  • 3
  • 2
  • might help . https://stackoverflow.com/questions/3738934/jpa-removing-child-from-collection?rq=1 – Vaibs Jan 19 '18 at 14:06
  • the `cascadeType` shouldn't pose any problem here. maybe the `saveOrUpdateEmployee`, the project isn't saved in the DB and therefore it can't be added and this might cause it to set a new one. – XtremeBaumer Jan 19 '18 at 14:10
  • I agree that Cascading seems to be ok. Maybe during passing Employee to `saveOrUpdateEmployee` method loses reference to `Set`. – F.Burian Jan 19 '18 at 14:14

1 Answers1

0

I found possible cause of my problem. When I submit the update form Spring creates new Instance of my Employee.class which means that Set<Project> becoming a new empty set. Since I'm passing in <form:hidden path="id"> id of my Employee, hibernate override all my values in DB including my collection of Projects.

Now I wonder how to prevent such behavior? <form:hidden path="projects"> doesn't work.

Using @InitBinder -> binder.setDisallowedFields({"projects"}) doesn't work either.

F.Burian
  • 3
  • 2