经过几天的折磨来解决这个问题并阅读我能找到的所有内容,我决定问一下。我无法理解我在Hibernate site上读到的内容,所以我将解释我的情况。
我的对象student
包含对象program
:
@ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE}, fetch=FetchType.EAGER)
@JoinColumn(name = "PROGRAM_FK", nullable = false)
private Program program;
在我的服务方法中,我想要仅为学生更改/更新程序:
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);
}
我想更改学生的程序,而不是程序本身。我怎样才能做到这一点?有人可以告诉我,在这种特殊情况下,谁是父母,谁是孩子?我应该使用CascadeType.MERGE吗?我应该使用merge()方法还是别的什么?我无法从阅读文档中推断出这一点,如果有人在这个特定情况下如此善意地解释它,那么我终于可以理解它了......谢谢。
程序对象:
@OneToMany(mappedBy="program")
private Set<Student> students;
我正在从控制器调用我的编辑方法:
@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";
}
}
答案 0 :(得分:1)
主要问题是您使用的输入包含太多您想要做的信息。这让一切都让人困惑。
您要做的就是在现有学生上设置现有课程。您完成此任务所需的唯一输入是学生ID和计划ID。如果你只有那些输入,解决方案就会变得很明显:
@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);
}
请注意,我使用load()
而非get()
来加载程序,因为您不需要程序状态,只需要对现有程序的引用。它也适用于get()
,但它会执行一个额外的,无用的seelct查询来加载程序的状态。