首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Hibernate 從入門到精通(十一):多對多雙向關聯映射完整解析

     編輯:Java 相關知識

前言

承接上篇「多對多單向關聯」,本文解析七大關聯映射的最後一種:多對多雙向關聯。重點對比單向與雙向的異同,掌握配置關鍵。

領域模型

public class Role {
    private int id;
    private String name;
    private Set users; // 雙向:Role 端持有 User 集合
    // getter/setter
}

public class User {
    private int id;
    private String name;
    private Set roles; // 雙向:User 端持有 Role 集合
    // getter/setter
}

兩端皆持有集合,形成雙向導航:role.getUsers()、user.getRoles()。

資料庫結構:與單向完全相同

中間表 t_user_role 維護關聯:

表欄位
t_userid (PK), name
t_roleid (PK), name
t_user_roleuser_id (FK), role_id (FK), PK(user_id, role_id)

結論:雙向關聯不改變資料庫結構,僅改變物件導航能力。

映射配置 (hbm.xml)

<class name="com.zs.hibernate.Role" table="t_role">
  <id name="id"><generator class="native"/></id>
  <property name="name"/>
  <set name="users" table="t_user_role">
    <key column="role_id" not-null="true"/>
    <many-to-many class="com.zs.hibernate.User" column="user_id"/>
  </set>
</class>

<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" not-null="true"/>
    <many-to-many class="com.zs.hibernate.Role" column="role_id"/>
  </set>
</class>

單向 vs 雙向 核心差異

維度單向雙向
導航User → Role (單向)User ↔ Role (雙向)
Java 類別單邊有 Set雙邊皆有 Set
映射配置單邊 <set> + many-to-many雙邊對稱配置
資料庫相同中間表相同中間表
關係對等性A→B ≠ B→AA↔B 等價

關鍵注意事項

  1. 雙向同步:在 Java 代碼中維護關聯時,雙邊都要設定:
    user.getRoles().add(role);
    role.getUsers().add(user); // 必須雙邊加入,否則記憶體不一致
  2. 避免無限遞迴:toString()、JSON 序列化、equals/hashCode 需排除集合或使用 @JsonIgnore、@ToString.Exclude
  3. 級聯操作:通常不建議在多對多雙向配置 cascade="all",刪除一方會誤刪另一方及關聯記錄。改由 Service 層顯式管理關聯。
  4. inverse="true":雙向多對多不需要設定 inverse(僅一對多雙向才需)。兩端皆為關聯擁有者,Hibernate 會對中間表執行兩次 INSERT/DELETE,可接受。

註解配置對照

@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 {
    @ManyToMany(mappedBy="roles") // mappedBy 指向擁有端
    private Set users = new HashSet<>();
}

註解中 僅一端維護關聯 (mappedBy),另一端為被動端,避免重複維護中間表。

系列總結

七大關聯映射已全部講解完畢:

  1. 一對一單向/雙向
  2. 一對多單向/雙向
  3. 多對一單向
  4. 多對多單向/雙向

下一階段將深入:繼承映射、元件映射、查詢語言 (HQL/Criteria)、快取策略、效能調優、鎖機制等進階主題。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved