许多对许多hibernate反面忽略了

时间:2012-09-23 13:24:55

标签: hibernate jpa-2.0

您正在阅读hibernate文档。

http://docs.jboss.org/hibernate/annotations/3.5/reference/en/html/entity.html

  

使用@ManyToMany在逻辑上定义了多对多关联   注解。您还必须描述关联表和   使用@JoinTable注释连接条件。如果关联是   双向的,一方必须是所有者,一方必须是   反向结束(即,在更新关系时将忽略它   关联表中的值):

我理解除了最后一切之外的一切

  

(即,在更新关联表中的关系值时将忽略它。)

这是什么意思?实施例

2 个答案:

答案 0 :(得分:27)

假设您有以下实体:

@Entity
public class Student {
    @ManyToMany
    private Set<Course> courses;
    ...
}

@Entity
public class Course {
    @ManyToMany(mappedBy = "courses")
    private Set<Student> students;
    ...
}

所有者方是学生(因为它没有mappedBy属性)。反面是Course((因为它具有mappedBy属性)。

如果您执行以下操作:

Course course = session.get(Course.class, 3L);
Student student = session.get(Student.class, 4L);
student.getCourses().add(course);

Hibernate将在联接表中为学生4和课程3添加一个条目,因为您更新了关联的所有者方(student.courses)。

然而,如果您执行以下操作:

Course course = session.get(Course.class, 3L);
Student student = session.get(Student.class, 4L);
course.getStudents().add(student);

什么都不会发生,因为你更新了关联的反面(course.students),但忽略了更新了所有者方面。 Hibernate只考虑所有者方。

答案 1 :(得分:2)

要使它以两种方式工作,您需要在实体之间建立两个独立的关系。 这可以通过数据库中的一个连接表来表示,但默认情况下它将由两个表示,因此您必须明确表示您想要一个连接表。

我将使用之前提到的学生和课程模型进行演示。

@Entity
public class Student {
    @ManyToMany
    @JoinTable(name = "student_course",
               joinColumns = {@JoinColumn(name = "courses_id")},
               inverseJoinColumns = {@JoinColumn(name = "students_id")})
    private Set<Course> courses;
    ...
}

@Entity
public class Course {
    @ManyToMany
    @JoinTable(name = "student_course",
               joinColumns = {@JoinColumn(name = "students_id")},
               inverseJoinColumns = {@JoinColumn(name = "courses_id")})
    private Set<Student> students;
    ...
}

在上面的示例中,我们与Student&lt; - &gt;课程关系的每一侧有2个关系,它们是一个关系的所有者。 因此,这解决了仅在所有者方面保存对数据库的更改的问题,因为每一方都是一个关系的所有者。

但是我们必须记住一个事实,即在保存数据之后,不会从数据库重新加载关系集合 所以程序员需要自己处理关系集合。通过这样说,我想说最简单的方法是 修改关系集合的setter以重建实体之间的循环,如下所示:

public void setCourses(Set<Course> courses) {
    for(Course c : courses) {
        if (!c.getStudents().contains(this)) {
            c.getStudents().add(this);
        }
    }
    this.courses = courses;
}

public void setStudents(Set<Student> students) {
    for(Student s : students) {
        if (!s.getCourses().contains(this)){
            s.getCourses().add(this);
        }
    }
    this.students = students;
}