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

Hibernate 多對多與一對多映射關係實戰

     編輯:Java 相關知識

前言

繼一對一映射後,本文將深入講解 Hibernate 中最常用的兩種集合映射:多對多與一對多。透過「學生-老師」經典場景,展示雙向關聯的實體設計、映射檔配置與關鍵屬性(如 inverse、cascade)的實戰意義。

一、多對多映射

業務場景

一個學生可選修多門課程(對應多位老師),一位老師可教授多名學生。資料庫需建立中間關聯表 t_s(student_id, teacher_id)。

實體類別

// Student.java
public class Student {
    private int id;
    private String sname;
    private Set<Teacher> teacherSet = new HashSet<>();  // 使用 Set 避免重複

    // getter/setter 略
    public Set<Teacher> getTeacherSet() { return teacherSet; }
    public void setTeacherSet(Set<Teacher> teacherSet) { this.teacherSet = teacherSet; }
}

// Teacher.java
public class Teacher {
    private int id;
    private String tname;
    private Set<Student> studentSet = new HashSet<>;

    public Set<Student> getStudentSet() { return studentSet; }
    public void setStudentSet(Set<Student> studentSet) { this.studentSet = studentSet; }
}

映射檔配置

<!-- Student.hbm.xml -->
<class name="com.entity.Student" table="student">
  <id name="id"><generator class="native"/></id>
  <property name="sname" column="sname"/>

  <set name="teacherSet" table="t_s" lazy="false" inverse="true" cascade="all">
    <key column="s_id"/>
    <many-to-many class="com.entity.Teacher" column="t_id" outer-join="auto"/>
  </set>
</class>

<!-- Teacher.hbm.xml -->
<class name="com.entity.Teacher" table="teacher">
  <id name="id"><generator class="native"/></id>
  <property name="tname" column="tname"/>

  <set name="studentSet" table="t_s" lazy="false" cascade="all">
    <key column="t_id"/>
    <many-to-many class="com.entity.Student" column="s_id" outer-join="auto"/>
  </set>
</class>

核心屬性解析

  • table="t_s":指定中間關聯表名稱。
  • inverse="true":關鍵! 表示關係由「另一端」維護。此處 Student 端設為 true,Teacher 端為 false(預設),避免雙方各自發出 INSERT/UPDATE 導致重複寫入中間表。
  • cascade="all":儲存老師時自動關聯學生(視業務而定,謹慎使用)。
  • lazy="false":關閉延遲載入,立即抓取集合(適合小數據量場景)。

二、一對多映射

業務場景

一位老師指導多名學生,但一名學生僅屬於一位老師。資料庫中 student 表含外鍵 t_id 指向 teacher。

實體類別

// Student.java(多方)
public class Student {
    private int id;
    private String sname;
    private Teacher teacher;  // 多對一關聯

    public Teacher getTeacher() { return teacher; }
    public void setTeacher(Teacher teacher) { this.teacher = teacher; }
}

// Teacher.java(一方)
public class Teacher {
    private int id;
    private String tname;
    private Set<Student> students = new HashSet<>();  // 一對多集合

    public Set<Student> getStudents() { return students; }
    public void setStudents(Set<Student> students) { this.students = students; }
}

映射檔配置

<!-- Student.hbm.xml -->
<class name="com.entity.Student" table="student">
  <id name="id"><generator class="native"/></id>
  <property name="sname" column="sname"/>

  <!-- 多對一:由 Student 端維護外鍵 -->
  <many-to-one name="teacher" class="com.entity.Teacher"
               column="t_id" cascade="all" outer-join="auto"/>
</class>

<!-- Teacher.hbm.xml -->
<class name="com.entity.Teacher" table="teacher">
  <id name="id"><generator class="native"/></id>
  <property name="tname" column="tname"/>

  <!-- 一對多:inverse="true" 表示由 Student 端的 many-to-one 維護關係 -->
  <set name="students" lazy="false" inverse="true" cascade="all">
    <key column="t_id"/>
    <one-to-many class="com.entity.Student"/>
  </set>
</class>

關鍵點總結

  1. 多對一是關係擁有者:外鍵在 student 表,故 <many-to-one> 不需 inverse,負責維護關聯。
  2. 一對多設 inverse="true":放棄關係維護權,避免 Hibernate 額外執行 UPDATE 更新外鍵欄位。
  3. cascade 選擇:若刪除老師需連帶刪除學生,設 cascade="delete" 或 "all";否則僅解除關聯。

最佳實踐建議

  • 集合優先使用 Set,避免重複元素;需排序可用 SortedSet 或 List(搭配 <index>)。
  • 大數據量場景務必開啟 lazy="true"(預設),搭配 OpenSessionInViewFilter 或 DTO 組裝避免 LazyInitializationException。
  • 雙向關聯務必在程式碼中雙向設值(如 teacher.getStudents().add(student); student.setTeacher(teacher);),確保記憶體中物件圖一致。

總結

多對多依賴中間表,一對多依賴外鍵欄位。掌握 inverse、cascade、lazy 三大屬性的語義與組合,是驅動 Hibernate 高效、正確處理集合關聯的關鍵。

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