關聯關系映射
關聯關系映射,是映射關系中比較複雜的一種映射關系,總的說來有一對一、一對多和多對多幾種關系。細分起來他們又有單向和雙向之分。下面我們逐一介紹一下。
單向 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 圖
Figure 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 圖
Figure 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 圖
Figure 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 對應得資料庫表
Figure 4. Teacher 對應得資料庫表
圖 5. Students 對應得資料庫表
Figure 5. Students 對應得資料庫表
圖 6. 中間生成表
Figure 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
}
圖 7. 雙向多對多關系對應的 ER 圖
Figure 7. 雙向多對多關系對應的 ER 圖