承接上篇「多對一單向關聯」,本文反向講解一對多單向關聯映射。二者角度不同:學生視角是多對一,班級視角是一對多,但對象關係建立方式迥異。
Hibernate透過操作「一」端(Class),間接/自動操作「多」端(Student)。添加班級時自動級聯添加學生,查詢班級可獲取所有學生。

public class Class {
private int id;
private String name;
private Set<Student> students; // 集合屬性持有多端引用
// getter/setter...
}
public class Student {
private int id;
private String name;
// getter/setter... // 學生端無班級引用(單向)
}
<hibernate-mapping package="com.bjpowernode.hibernate">
<class name="Student" table="t_student">
<id name="id"><generator class="native"/></id>
<property name="name"/>
</class>
<class name="Class" table="t_class">
<id name="id"><generator class="native"/></id>
<property name="name"/>
<!-- Set集合關聯多個學生 -->
<set name="students">
<!-- 在t_student建外鍵classid指向本表id -->
<key column="classid"></key>
<one-to-many class="Student"/>
</set>
</class>
</hibernate-mapping>
one-to-many自動在t_student建立外鍵classid映射t_class.id。

public class One2ManyTest extends TestCase {
public void testSave2() {
Session session = HibernateUtils.getSession();
session.beginTransaction();
Student student1 = new Student(); student1.setName("張三");
Student student2 = new Student(); student2.setName("李四");
// 必須先save轉為Persistent狀態,否則拋TransientObjectException
session.save(student1); session.save(student2);
Class classes = new Class(); classes.setName("提高班");
Set<Student> students = new HashSet<>();
students.add(student1); students.add(student2);
classes.setStudents(students);
session.save(classes); // 可成功保存
session.getTransaction().commit();
}
}
執行前後數據對比:

| 關聯類型 | 維護關係 | 加載行為 | 缺陷 |
|---|---|---|---|
| 多對一 | 多指向一 | 加載多時自動加載一 | — |
| 一對多 | 一指向多 | 加載一時自動加載多 | 見下文 |
classid=null。若資料庫設NOT NULL將無法保存。classid=NULL,再UPDATE設置外鍵。產生額外SQL開銷。解決方案:改用雙向關聯(下篇講解),由「多」端維護關係,inverse="true"關閉「一」端維護。