Hibernate,JPA 對象關係映射之關聯關係映射策略
關聯關係映射
關聯關係映射,是映射關係中比較複雜的一種映射關係,總的說來有一對一、一對多和多對多幾種關係。細分起來他們又有單向和雙向之分。
3 評論
關聯關係映射
關聯關係映射,是映射關係中比較複雜的一種映射關係,總的說來有一對一、一對多和多對多幾種關係。細分起來他們又有單向和雙向之分。下面我們逐一介紹一下。
單向 OneToOne
單向一對一是關聯關係映射中最簡單的一種,簡單地說就是可以從關聯的一方去查詢另一方,卻不能反向查詢。我們用下面的例子來舉例說明,清單 1 中的 Person 實體類和清單 2 中的 Address 類就是這種單向的一對一關係,我們可以查詢一個 Person 的對應的 Address 的內容,但是我們卻不能由一個 Address 的值去查詢這個值對應的 Person。
清單 1. 單向一對一關係的擁有端
@Entity public class Person implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String name; private int age; @OneToOne private Address address; // Getters & Setters }
清單 2. 單向一對一關係的反端
@Entity public class Address implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String street; private String city; private String country; // Gettes& Setters }
圖 1. 單向一對一關係對應的 ER 圖
從圖 1 他們的 ER 圖上可以看出,這種單向的一對一關係在數據庫中是以外鍵的形式被映射的。其中關係的發出端存儲一個指向關係的接收端的一個外鍵。在這個例子中 Person 表中的 ADDRESS_ID 就是指向 address 標的一個外鍵,缺省情況下這個外鍵的字段名稱,是以它指向的表的名稱加下劃線“_”加“ID”組成的。當然我們也可以根據我們的喜好來修改這個字段,修改的辦法就是使用 @JoinColumn 這個註解。在這個例子中我們可以將這個註解註釋在 Person 類中的 Address 屬性上去。
雙向 OneToOne
雙向關係有一方爲關係的擁有端,另一方是關係的反端,也就是“Inverse”端。在這裏例子中 Person 擁有這個關係,而 Address 就是關係的“Inverse”端。Address 中我們定義了一個 person 屬性,在這個屬性上我們使用了 @OneToOne 註解並且定義了他的“mappedBy”屬性,這個在雙向關係的“Inverse”端是必需的,在下面將要介紹的雙向關係中也要用到這個屬性。
清單 3. 雙向一對一關係中的接受端
@Entity public class Address implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String street; private String city; private String country; @OneToOne(mappedBy = "address") private Person person; // Gettes& Setters }
單向 OneToMany
單向關係的一對多我們可以用清單 4 和清單 5 來說明。在關係的發出端 Person 中我們使用 OneToMany 這個註解對 cellPhones 這個屬性進行了註釋,cellPhones 中存儲的是 CellPhone 的一個 List 對象,JPA 就是用這種方式實現一對多的。
清單 4. 單向一對多關係的發出端
public class Person implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String name; private int age; @OneToMany private List<CellPhone> cellPhones; // Getters and Setters }
清單 5. 單向一對多關係的接收端
@Entity public class CellPhone implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String manufacture; private String color; private Long phoneNo; // Getters and Setters }
圖 2. 單向一對多關係對應的 ER 圖
在一對多關聯關係映射中,默認是以中間表的方式來映射這種關係的。如在本例中,中間表爲 person_cellphone,表的名稱爲關係的擁有端和 Inverse 端中間用下劃線連接。中間表的字兩個字段分別爲兩張表的得表名加下劃線“_”加 ID 組成。當然我們也可以改表這種默認的中間表的映射方式,我們可以在關係的擁有端使用 @JoinClolum 來使用外鍵的方式映射這個關係。
雙向 OneToMany
清單 6. 雙向一對多關係的接受端
@Entity public class Person implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String name; private int age; @OneToMany(mappedBy = "person") private List<CellPhone> cellPhones; // Getters and Setters }
清單 7. 雙向一對多關係的發出端
@Entity public class CellPhone implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String manufacture; private String color; private Long phoneNo; @ManyToOne private Person person; // Getters and Setters }
圖 3. 雙向一對多關係對應的 ER 圖
單向 ManyToMany
多對多關聯關係中只能通過中間表的方式進行映射。本例的單向多對多關係如下所示。
在清單 8 中我們使用了 ManyToMany 這個註解來對 Teacher 中的 Students 進行註釋,其中 Teacher 就是關係的發出端。而在 Student 中我們並沒有作任何定義,這是單向多對多的所要求的。
清單 8. 單向多對多關係的發出端
@Entity public class Teacher implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String name; private Boolean gender; private int age; private int height; @ManyToMany private List<Student> students; // Getters and Setters }
清單 9. 單向多對多關係的反端
@Entity public class Student implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String name; private Boolean gender; private int age; private int height; //Getters and Setters }
圖 4. Teacher 對應得數據庫表
圖 5. Students 對應得數據庫表
圖 6. 中間生成表
雙向 ManyToMany
清單 10. 雙向多對多關係的擁有端
@Entity public class Teacher implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String name; private Boolean gender; private int age; private int height; @ManyToMany private List<Student> students; // Getters and Setters }
清單 11. 雙向多對多關係的反端
@Entity public class Student implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String name; private Boolean gender; private int age; private int height; @ManyToMany(mappedBy = "students") private List<Teacher> teachers; //Getters and Setters }