**Component(組合/嵌入式值型別)**:擁有者生命週期完全綁定的值型別物件,**無獨立主鍵、無獨立資料表**,資料扁平化儲存在擁有者的資料表中。相當於「將多個欄位組合成一個有意義的領域物件」。
CREATE TABLE user (
id PK, name, age, email VARCHAR(100) NOT NULL
);
public class MailAddress {
private String email;
public void sendMail() { System.out.println("Send mail to " + email); }
// getter/setter ...
}
public class User {
private Integer id;
private String name;
private Integer age;
private MailAddress mailAddress; // Component
// getter/setter ...
}
<component><class name="com.hb3.pack_05.model.User" table="user">
<id name="id" .../>
<property name="name"/>
<property name="age"/>
<component name="mailAddress" class="com.hb3.pack_05.model.MailAddress">
<property name="email" column="email" type="string" not-null="true"/>
</component>
</class>
name="mailAddress":User 中的屬性名。class:Component 實際類別。<property> 映射到同一張表的欄位。MailAddress addr = new MailAddress();
addr.setEmail("bluelazysb@hotmail.com");
User user = new User();
user.setName("shenbin");
user.setAge(28);
user.setMailAddress(addr);
session.save(user); // 單一 INSERT,email 欄位同步寫入
// 載入後可直接呼叫領域方法
user = (User) session.load(User.class, 1);
user.getMailAddress().sendMail(); // 輸出: Send mail to bluelazysb@hotmail.com
| 特性 | 說明 | |
|---|---|---|
| 生命週期綁定 | User 刪除 → MailAddress 自動刪除;無獨立儲存/刪除 | |
| 無主鍵 | 不需實作 equals/hashCode(除非放入 Set) | |
| 支援巢狀 | Component 內可再包含 Component | |
| 支援集合 | <set> + <composite-element> 可建立 Component 集合 | |
| 可為 null | 若所有欄位皆 null,Hibernate 將整個 Component 視為 null |
| 維度 | Entity (一對一) | Component |
|---|---|---|
| 資料表 | 獨立表 | 同表扁平化 |
| 主鍵 | 有 | 無 |
| 共享引用 | 可被多 Entity 參考 | 僅屬於單一擁有者 |
| 獨立載入 | 可 | 不可 |
| 適用場景 | 獨立業務實體 | 值物件、領域概念封裝 |
**優先使用 Component 進行領域建模**(如 Address、Money、Name、DateRange 等值物件),只有當物件需要獨立身分、被多方引用、或有獨立生命週期時,才升級為 Entity。這符合 DDD「值物件優先」原則,也能獲得更佳效能(少 JOIN、少快取管理)。