2012-09-23 105 views
7

您好,我正在閱讀hibernate文檔。多對多休眠反面忽略

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

甲許多一對多關聯被定義邏輯上使用@ManyToMany 註釋。您還必須使用@JoinTable註釋來描述關聯表和連接條件。如果該關聯是 雙向的,一側具有成爲所有者和一側必須是 逆端部(即,其將更新的關係中的對應表 值時被忽略。):

我瞭解除最後一項以外的所有內容

(即更新關聯表中的關係值時將被忽略)。

這是什麼意思?例?

回答

22

假設你有以下實體:

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

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

的業主方是學生(因爲它不具備mappedBy屬性)。反方當然是((因爲它有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只考慮所有者方。

+0

謝謝!非常好的解釋。所以唯一的辦法是更新所有者?雙方都不能成爲所有者?如果我希望它能夠雙向工作?不可能? – pethel

+0

是的,你必須更新所有者方。只有一方可以成爲所有者。沒有辦法使它同時工作。 –

+0

@JBNizet,你對下面的答案有什麼看法? – azerafati

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; 
    ... 
} 

在上面的例子中,我們有與學生<的每一側2間的關係 - 一個關係>課程關係是所有者。 因此,這解決了僅在所有者一方保存對數據庫的更改的問題,因爲每一方都是一個關係的所有者。

但是我們必須記住一個事實,即在保存數據之後,關係集合將不會從數據庫 重新加載,因此程序員需要自己處理關係集合。說這個,我想說的是,最簡單的方法就是修改 的制定者收藏的關係,重建實體之間的週期是這樣的:

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; 
}