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

One to many relationship without reference in 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();

学校实体不需要 MappedBy

public class School{
....
@OneToMany(cascade = CascadeType.ALL)
@JoinColumn(name = "school_id")
private Set<Student> studentSet = new HashSet<Student>(0);

并且不要在学生实体中使用学校

public class Student {
....

}

@Funtik 方法是正确的,但是它需要第三个 table.

不过你的做法也是对的。您可以使这种关系成为双向的。 如果你想让你的 school_id_fknot null 你可以使用 休眠中的一种常见模式(所谓的)便捷方法:

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 因为只有休眠应该使用 setStudentSet() setter。 私人 setter 会这样做。但是您可以公开 public API 来对该集合进行操作 - 在本例中为 addStudent()。 在 addStudent(student) 方法中 student 对象以 封装的方式 .

添加到集合并分配给父学校

总结: 这是使用休眠时的常见模式,隐藏集合 setter,公开像 addStudent() 这样的便捷方法。 在这种方法中,您始终填充 FK 列,并且无需 HQL 查询即可从 Student 对象中获取 School 对象。在这种情况下不需要第三个 table。

这只是@Funtik 解决方案的替代方案。