在Hibernate中没有引用的一对多关系

时间:2015-01-04 13:26:37

标签: java hibernate

如你所见,我有一对多的关系。我想要做的是我想用学生对象保存学校对象而不设置学生对象学校。下面的代码可以工作但是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();

2 个答案:

答案 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 {
....

}