在 Java 持久層開發中,Hibernate 作為經典的 ORM 框架,其關聯映射功能是核心技能之一。本文將透過完整的資料表設計、POJO 類別、映射檔案(HBM)以及應用程式範例,詳細講解 多對一 與 一對多 兩種最常見的關聯關係映射方式。
多對一關係指:多個實體關聯同一個實體。例如:多位員工共用同一個地址。
address 指向地址表。id。CREATE TABLE EMPLOYEE (
id INT NOT NULL AUTO_INCREMENT,
first_name VARCHAR(20) DEFAULT NULL,
last_name VARCHAR(20) DEFAULT NULL,
salary INT DEFAULT NULL,
address INT NOT NULL,
PRIMARY KEY (id)
);
CREATE TABLE ADDRESS (
id INT NOT NULL AUTO_INCREMENT,
street_name VARCHAR(40) DEFAULT NULL,
city_name VARCHAR(40) DEFAULT NULL,
state_name VARCHAR(40) DEFAULT NULL,
zipcode VARCHAR(10) DEFAULT NULL,
PRIMARY KEY (id)
);
Employee 類別持有 Address 類型的屬性,體現多對一關係。
public class Employee {
private int id;
private String firstName;
private String lastName;
private int salary;
private Address address; // 多對一關聯
// 建構子、Getter/Setter 略
}
public class Address {
private int id;
private String street;
private String city;
private String state;
private String zipcode;
// 建構子、Getter/Setter 略
}
使用 <many-to-one> 元素建立關聯,name 對應 POJO 中的屬性名,column 指定外鍵欄位,class 指向關聯實體類別。
<hibernate-mapping>
<class name="Employee" table="EMPLOYEE">
<id name="id" column="id">
<generator class="native"/>
</id>
<property name="firstName" column="first_name"/>
<property name="lastName" column="last_name"/>
<property name="salary" column="salary"/>
<many-to-one name="address" column="address" class="Address" not-null="true"/>
</class>
<class name="Address" table="ADDRESS">
<id name="id" column="id">
<generator class="native"/>
</id>
<property name="street" column="street_name"/>
<property name="city" column="city_name"/>
<property name="state" column="state_name"/>
<property name="zipcode" column="zipcode"/>
</class>
</hibernate-mapping>
ManageEmployee 類別示範新增、查詢、更新、刪除操作,並驗證兩位員工共用同一地址的資料庫狀態。
一對多關係指:一個實體關聯多個實體。例如:一位員工擁有多張證書。
employee_id 指向員工表。Employee 類別持有 Set<Certificate> 集合,使用 HashSet 避免重複。
public class Employee {
private int id;
private String firstName;
private String lastName;
private int salary;
private Set<Certificate> certificates = new HashSet<>(); // 一對多關聯
// 建構子、Getter/Setter 略
}
public class Certificate {
private int id;
private String name;
// 建構子、Getter/Setter 略
}
使用 <set> 元素映射集合,<key> 指定外鍵欄位,<one-to-many> 宣告關聯類別。cascade="all" 表示級聯操作。
<hibernate-mapping>
<class name="Employee" table="EMPLOYEE">
<id name="id" column="id">
<generator class="native"/>
</id>
<property name="firstName" column="first_name"/>
<property name="lastName" column="last_name"/>
<property name="salary" column="salary"/>
<set name="certificates" cascade="all">
<key column="employee_id"/>
<one-to-many class="Certificate"/>
</set>
</class>
<class name="Certificate" table="CERTIFICATE">
<id name="id" column="id">
<generator class="native"/>
</id>
<property name="name" column="certificate_name"/>
</class>
</hibernate-mapping>
同樣透過 ManageEmployee 類別進行 CRUD 操作,驗證員工與證書的關聯資料正確寫入資料庫。
<many-to-one>,外鍵儲存在主表。<set> + <one-to-many>,外鍵儲存在從表。inverse="true" 優化效能,由關係維護端控制外鍵更新。cascade 屬性簡化級聯儲存/刪除邏輯。掌握 Hibernate 的關聯映射,能讓物件模型與關聯式資料庫無縫銜接。實務上建議優先使用註解或 JPA 規範,但理解 HBM XML 映射原理對除錯與維護舊系統仍有重要價值。