| Java 介面 | 映射標籤 | 資料表特徵 | 特性 |
|---|---|---|---|
| Set | <set> | 無索引欄位,主鍵為 (外鍵, 元素值) | 不重複、無序 |
| List | <list> | 有 <index> 欄位記錄位置 | 有序、可重複 |
| Bag | <bag> | 無索引,主鍵僅外鍵,允許重複 | 無序、可重複 |
| Map | <map> | 有 <map-key> 欄位 | Key-Value、Key 唯一 |
CREATE TABLE user (id PK, name);
CREATE TABLE email (id FK, address); -- 主鍵 (id, address)
<set name="emails" table="email">
<key column="id"/>
<element type="java.lang.String" column="address"/>
</set>
特點:**同一 User 下 Email 不可重複**。
CREATE TABLE item (id FK, position INT, name); -- 主鍵 (id, position)
<list name="items" table="item">
<key column="id"/>
<index column="position"/>
<element type="java.lang.String" column="name"/>
</list>
插入順序會持久化到 position 欄位,讀取時自動按位置排序。
CREATE TABLE item (id FK, name); -- 無主鍵,允許完全重複列
<bag name="items" table="item">
<key column="id"/>
<element column="name" type="java.lang.String"/>
</bag>
效能陷阱:更新時無法定位具體行,Hibernate 採取 **全刪重寫** 策略:
DELETE FROM item WHERE id=?
INSERT INTO item (id, name) VALUES (?, ?) ...
<idbag> 引入代理主鍵CREATE TABLE item (cid CHAR(32) PK, id FK, name);
<idbag name="items" table="item">
<collection-id column="cid" type="java.lang.String">
<generator class="uuid.hex"/>
</collection-id>
<key column="id"/>
<element column="name" type="java.lang.String"/>
</idbag>
更新時可精準 DELETE WHERE cid=?,效能大幅提升。
CREATE TABLE item (id FK, name VARCHAR, price DECIMAL); -- 主鍵 (id, name)
<map name="items" table="item">
<key column="id"/>
<map-key column="name" type="java.lang.String"/>
<element column="price" type="java.math.BigDecimal"/>
</map>
使用 <composite-element> 替代 <element>:
<set name="emails" table="email">
<key column="id"/>
<composite-element class="com.hb3.pack_15.model.MailAddress">
<property name="address" column="address"/>
</composite-element>
</set>
<set> 加 order-by="address DESC"(需資料庫支援)。SortedSet + 實作 Comparator,映射加 sort="com.xxx.MyComparator"。集合預設 lazy="true"。存取集合大小或迭代時才發 SQL。
需在 Session 關閉前初始化,或使用 Hibernate.initialize(collection) 強制載入,否則會拋 LazyInitializationException。