Properly modify object with @ManyToOne relationship in Spring MVC + Hibernate app

核能气质少年 提交于 2020-01-03 02:51:57

问题


After days of torture to resolve this issue and reading everything I could find on SO I decided to ask. I'm having trouble understanding what I read here on Hibernate site, so I'll explain my situation.

I have object student that contains object program:

@ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE}, fetch=FetchType.EAGER)
@JoinColumn(name = "PROGRAM_FK", nullable = false)
private Program program;

In my service method I want o change/update only program for a student:

 public void edit(Student student) {
     Session session = sessionFactory.getCurrentSession();

     // Retrieve existing student via id
     Student existingStudent = (Student) session.get(Student.class, student.getStudentId());

     // Assign updated program to this student
     existingStudent.setProgram(student.getProgram()); <-- This is not working as I would want it! -->

     session.merge(existingStudent);
 }

I want to change the program for the student, but not the program itself. How can I achieve this? And can someone please tell me, in this particular situation, who is parent and who is child? Should I use CascadeType.MERGE at all? Should I use merge() method or something else? I can't deduce this from reading documentation, if someone would be so kind to explain it on this particular case, so I can finally understand it... Thank you.

Program object:

@OneToMany(mappedBy="program")
private Set<Student> students;

I'm calling my edit method from controller:

    @RequestMapping(value="/edit", method = RequestMethod.POST, params="edit")
    public String postEditStudent(
            @Validated({Student.StudentEditChecks.class}) @ModelAttribute("studentAttribute") Student student,
            BindingResult result,
            Model model) {

        logger.debug("Received request to edit student");

        if (result.hasErrors()) {
            model.addAttribute("programList", programService.getAll());
            return "editStudent";
        }
        else {
            studentService.edit(student);
            return "redirect:/essays/main/student/list";
        }
    }

回答1:


The main problem is that you use inputs that contain too much information for what you want to do. And that makes everything confusing.

All you want to do is setting an existing program on an existing student. The only inputs you need for this task are the student ID and the program ID. And if you had only those inputs, the solution would become obvious:

@Transactional
public void setProgramOnStudent(Long studentId, Long programId) {
    Student student = (Student) session.get(Student.class, studentId);
    Program program = (Program) session.load(Program.class, programId);
    student.setProgram(program);
}

Note that I used load() and not get() to load the program, because you don't ven need th state of the program, only a reference to the existing program. It would also work with get(), but it would execute an additional, useless seelct query to load the state of the program.



来源:https://stackoverflow.com/questions/21550585/properly-modify-object-with-manytoone-relationship-in-spring-mvc-hibernate-ap

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!