如你所见,我有一对多的关系。我想要做的是我想用学生对象保存学校对象而不设置学生对象学校。下面的代码可以工作但是hibernate会将空值插入到school_id_fk列。
public class Student {
....
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "school_id_fk")
private School school;
}
public class School{
....
@OneToMany(cascade = CascadeType.ALL, mappedBy = "school")
private Set<Student> studentSet = new HashSet<Student>(0);
}
和主要方法;
School school = new School();
school.setSchoolName("school name");
Student student = new Student();
student.setStudentName("studentname1");
student.setStudentSurname("studentsurname1");
//student.setSchool(school); I don't want to set this line
Student student2 = new Student();
student2.setStudentName("studentname2");
student2.setStudentSurname("studentsurname2");
//student2.setSchool(school); I don't want to set this line
SessionFactory sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
session.beginTransaction();
school.getStudentSet().add(student);
school.getStudentSet().add(student2);
session.save(school);
session.getTransaction().commit();
session.close();
sessionFactory.close();
答案 0 :(得分:2)
@Funtik方法是正确的,但它需要第三个表。
但你的方法也是正确的。您可以将此关系设置为双向。
如果您希望school_id_fk
列不为空,则可以使用
hibernate中的常见模式(所谓的)便捷方法:
public class Student {
....
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "school_id_fk")
private School school;
}
public class School{
....
@OneToMany(cascade = CascadeType.ALL, mappedBy = "school")
private Set<Student> studentSet;
// this is private setter (used by hibernate internally)
private void setStudentSet(Set<Student> studentSet) {
this.studentSet = studentSet;
}
// this is public method (exposed API)
public void addStudent(Student) {
if (studentSet == null) {
studentSet = new HashSet<>();
}
student.setSchool(this);
studentSet.add(student);
}
}
正如您所看到的(根据此模式),您应该隐藏studentSet
,因为只有hibernate应该使用setStudentSet()
setter。
私人制定者会这样做。但是在这种情况下,您可以公开公共API来对此集合进行操作 - addStudent()
。
在addStudent(student)
方法中添加student
对象,以封装的方式设置并分配到家庭学校。
摘要:这是使用hibernate,隐藏集合设置器,公开addStudent()
等便捷方法的常见模式。
在这种方法中,您的FK列始终填充,您可以从School
对象获取Student
对象,而无需HQL查询。在这种情况下不需要第三张表。
这只是@Funtik解决方案的替代品。
答案 1 :(得分:1)
学校实体不需要MappedBy
public class School{
....
@OneToMany(cascade = CascadeType.ALL)
@JoinColumn(name = "school_id")
private Set<Student> studentSet = new HashSet<Student>(0);
并且不要在学生实体中使用学校
public class Student {
....
}