繼一對多雙向關聯後,進入多對多映射。本文解析多對多單向關聯,對比一對多單向異同,掌握中間表機制。
public class Role { // 被動端,無導航
private int id;
private String name;
// getter/setter
}
public class User { // 主動端,持有 Role 集合
private int id;
private String name;
private Set roles; // 單向導航:User → Role
// getter/setter
}
| 特徵 | 一對多單向 | 多對多單向 |
|---|---|---|
| 關聯端基數 | 一 → 多 | 多 → 多 |
| 外鍵位置 | 多的一方表加外鍵 | 需第三張中間表 |
| 映射標籤 | <one-to-many> | <many-to-many> |
| 導航方向 | 單向 | 單向 |
| 表 | 欄位 |
|---|---|
| t_user | id (PK), name |
| t_role | id (PK), name |
| t_user_role | user_id (FK), role_id (FK), PK(user_id, role_id) |
中間表 t_user_role 解決「多對多無法在單表加外鍵」的難題。
<class name="com.zs.hibernate.User" table="t_user">
<id name="id"><generator class="native"/></id>
<property name="name"/>
<set name="roles" table="t_user_role">
<key column="user_id"/>
<many-to-many class="com.zs.hibernate.Role" column="role_id"/>
</set>
</class>
<class name="com.zs.hibernate.Role" table="t_role">
<id name="id"><generator class="native"/></id>
<property name="name"/>
<!-- 無導航,無 set 配置 -->
</class>
<set name="roles" table="t_user_role">:指定中間表名<key column="user_id"/>:中間表中指向 User 的外鍵欄<many-to-many class="Role" column="role_id"/>:指向 Role 的外鍵欄,標記為多對多@Entity @Table(name="t_user")
public class User {
@ManyToMany
@JoinTable(name="t_user_role",
joinColumns=@JoinColumn(name="user_id"),
inverseJoinColumns=@JoinColumn(name="role_id"))
private Set roles = new HashSet<>();
}
@Entity @Table(name="t_role")
public class Role {
// 無註解,純被動
}
下篇將講解多對多雙向關聯映射,實現 Role → User 反向導航,並對比註解 mappedBy 機制。