您正在阅读hibernate文档。
http://docs.jboss.org/hibernate/annotations/3.5/reference/en/html/entity.html
使用@ManyToMany在逻辑上定义了多对多关联 注解。您还必须描述关联表和 使用@JoinTable注释连接条件。如果关联是 双向的,一方必须是所有者,一方必须是 反向结束(即,在更新关系时将忽略它 关联表中的值):
我理解除了最后一切之外的一切
(即,在更新关联表中的关系值时将忽略它。)
这是什么意思?实施例
答案 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;
}