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

Hibernate 從入門到精通(九):一對多雙向關聯映射深度解析

     編輯:Java 相關知識

前言

承接一對多單向關聯,本文解析一對多雙向關聯。核心在於「多的一方」新增對「一的一方」的引用,並配置 <many-to-one> 實現反向導航。

領域模型

public class Classes { // 一的一方
    private int id;
    private String name;
    private Set students; // 集合
    // getter/setter
}

public class Student { // 多的一方
    private int id;
    private String name;
    private Classes classes; // 單一引用,關鍵差異
    // getter/setter
}

資料庫結構:與單向相同

表欄位
t_classesid (PK), name
t_studentid (PK), name, classesid (FK)

外鍵 classesid 在多的一方 (Student) 表中,結構無變化。

映射配置 (hbm.xml) 關鍵差異

<class name="com.zs.hibernate.Classes" table="t_classes">
  <id name="id"><generator class="native"/></id>
  <property name="name"/>
  <set name="students" inverse="true"> <!-- 關鍵:inverse="true" -->
    <key column="classesid"/>
    <one-to-many class="com.zs.hibernate.Student"/>
  </set>
</class>

<class name="com.zs.hibernate.Student" table="t_student">
  <id name="id"><generator class="native"/></id>
  <property name="name"/>
  <many-to-one name="classes" column="classesid"/> <!-- 關鍵:many-to-one -->
</class>

兩大關鍵配置解析

配置位置作用
inverse="true"一的一方 <set>宣告「關係維護權」在多的一方,避免 Hibernate 重複執行 INSERT/UPDATE 中間表
<many-to-one>多的一方建立反向導航,映射外鍵欄位,使 Student 能獲取 Classes

為什麼需要 inverse="true"?

  • 雙向關聯中,關聯由雙邊在記憶體維護:classes.getStudents().add(student) + student.setClasses(classes)
  • 若無 inverse="true",Hibernate 會在持久化時雙邊各執行一次 SQL,導致重複更新外鍵、效能損耗甚至死鎖
  • 設定 inverse="true" 告訴 Hibernate:「以多的一方 (Student) 為準,一的一方 (Classes) 不要管外鍵更新」

雙向同步最佳實踐

// 在 Classes 側提供便利方法,確保雙邊同步
public class Classes {
    public void addStudent(Student student) {
        students.add(student);
        student.setClasses(this); // 關鍵:同步反向引用
    }
    public void removeStudent(Student student) {
        students.remove(student);
        student.setClasses(null);
    }
}

常見錯誤

  1. 忘記 inverse="true" → 雙重更新外鍵
  2. 只設單邊 (如只 classes.getStudents().add(s) 忘 s.setClasses(c)) → 記憶體不一致、外鍵可能為 null
  3. 在多的一方也加 inverse → 錯誤,inverse 只能用在集合端

註解配置對照

@Entity @Table(name="t_classes")
public class Classes {
    @OneToMany(mappedBy="classes") // mappedBy 指向多的一方欄位名
    private Set students = new HashSet<>();
}

@Entity @Table(name="t_student")
public class Student {
    @ManyToOne
    @JoinColumn(name="classesid")
    private Classes classes;
}

註解天然以 mappedBy 宣告非維護端,無需 inverse。

下一步預告

下篇進入多對多映射:單向 → 雙向,中間表機制、雙向同步、mappedBy 實戰。

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