本文整理自北京尚學堂馬士兵 Hibernate 課程筆記,涵蓋六大關聯類型的註解配置、生成表結構、雙向維護技巧。
| 關聯類型 | 擁有端註解 | 被擁有端註解(雙向) | 外鍵位置 |
|---|---|---|---|
| 一對一 | @OneToOne @JoinColumn | @OneToOne(mappedBy="...") | 任意一方(通常主鍵共享或獨立外鍵) |
| 多對一 | @ManyToOne @JoinColumn | @OneToMany(mappedBy="...") | 多的一方(表) |
| 一對多 | @OneToMany @JoinColumn | @ManyToOne(mappedBy="...") | 多的一方(表) |
| 多對多 | @ManyToMany @JoinTable | @ManyToMany(mappedBy="...") | 中間表 |
@Entity
public class Husband {
@Id @GeneratedValue
private int id;
private String name;
@OneToOne
@JoinColumn(name="wifeId") // 指定外鍵列名
private Wife wife;
// getter/setter
}
@Entity
public class Wife {
@Id @GeneratedValue
private int id;
private String name;
// 無 husband 引用
}
生成表:Husband(wifeId FK → Wife.id)。若無 @JoinColumn,預設外鍵列為 wife_id。
@Entity
public class Wife {
@Id @GeneratedValue
private int id;
private String name;
@OneToOne(mappedBy="wife") // 關鍵:外鍵由 Husband.wife 維護
private Husband husband;
}
生成表:Wife 表無外鍵,僅 Husband 表有 wifeId。雙向導航皆可用,資料庫無冗余列。
@Entity
public class Dream {
@Id @GeneratedValue
private int id;
private String description;
@ManyToOne
@JoinColumn(name="personId")
private Person person;
}
外鍵在多的一方(Dream 表),單向只能從 Dream 找 Person。
@Entity
public class Person {
@Id @GeneratedValue
private int id;
private String name;
@OneToMany
@JoinColumn(name="personId") // 在 Dream 表加 personId FK
private Set dreams = new HashSet<>();
}
集合類型可用 Set/List/Map,資料庫表結構同多對一單向。
@Entity
public class Dream {
@ManyToOne
@JoinColumn(name="personId")
private Person person;
}
@Entity
public class Person {
@OneToMany(mappedBy="person") // 關鍵:由 Dream.person 維護關聯
private Set dreams = new HashSet<>();
}
資料庫僅 Dream 表有 personId,雙向導航完美。
@Entity
public class Teacher {
@Id @GeneratedValue
private int id;
private String name;
@ManyToMany
@JoinTable(
name="t_s",
joinColumns=@JoinColumn(name="teacher_id"),
inverseJoinColumns=@JoinColumn(name="student_id")
)
private Set students = new HashSet<>();
}
生成中間表 t_s(teacher_id, student_id, PK(teacher_id, student_id)),雙向外鍵約束。
@Entity
public class Student {
@ManyToMany(mappedBy="students") // 關鍵:由 Teacher.students 維護
private Set teachers = new HashSet<>();
}
中間表不變,Student 端獲得導航能力。
mappedBy:指明關聯維護端,避免雙向外鍵冗余與更新衝突。Set:資料庫記錄無序唯一,Set 語意最貼切;List 需額外維護索引列。@JoinColumn 名稱建議顯式指定,避免預設命名風格不一致。@JoinTable 中 joinColumns 指向擁有端,inverseJoinColumns 指向被擁有端。