| Java 接口 | Hibernate 映射標簽 | 特徵 | 底層表結構 |
|---|---|---|---|
java.util.List | <list> | **有序、允許重複**、需索引列 | 關聯表需 index_column |
java.util.Set | <set> | **無序、不允許重複** (依賴 equals/hashCode) | 關聯表無索引列,主鍵為 (FK + 元素值) |
java.util.Collection / List | <bag> / <idbag> | **無序、允許重複**、無索引列 | Bag: 無主鍵 (允許全重複行);idBag: 有代理主鍵 |
java.util.Map | <map> | 鍵值對映射 | 關聯表需 key 列 |
// 註解方式
@OneToMany(mappedBy = "parent")
@OrderColumn(name = "display_order") // 關鍵:維護索引列
private List children = new ArrayList<>();
// XML 方式
<list name="children" cascade="all-delete-orphan">
<key column="parent_id"/>
<list-index column="display_order"/> <!-- 索引列 -->
<one-to-many class="Child"/>
</list>
@OrderColumn / <list-index> 指定**索引列**,Hibernate 自動維護 0-based 索引值。List (而非 ArrayList) 以便 Hibernate 注入持久化包裝器。private List children = new ArrayList<>(); // 註解 (Hibernate 擴展)
@OneToMany(mappedBy = "parent")
@org.hibernate.annotations.CollectionType(type = "bag") // 或直接用 List 不加 @OrderColumn
private List children = new ArrayList<>();
// XML
<bag name="children" cascade="all-delete-orphan">
<key column="parent_id"/>
<one-to-many class="Child"/>
</bag>
parent_id,允許重複行 (同一父對象關聯多個完全相同的子對象)。<idbag name="children" cascade="all-delete-orphan">
<collection-id column="id" type="long">
<generator class="identity"/>
</collection-id>
<key column="parent_id"/>
<one-to-many class="Child"/>
</idbag>
collection-id),每行唯一標識。(parent_id, child_columns...)。equals() 和 hashCode() (基於業務鍵,非 ID)。開始 │ ├─ 需要保持插入順序/支持索引訪問? ──是──► List (小數據量/尾部操作) / 獨立排序字段 + Set │ ├─ 允許重複元素? ──是──► idBag (中大數據量) / Bag (極小/只讀) │ └─ 否 (不重複、無序) ──► Set (默認首選)
nullable=false,否則加載報錯。ORDER BY 或改用 List/Set + Comparator。cascade=ALL 實現「從集合移除即刪除實體」,適用於強生命周期綁定的聚合根。List = 有序 + 索引維護成本高;Bag = 無序 + 全量重寫極差;idBag = Bag + 代理鍵優化;Set = 無序去重 + 高性能 + 標準語義。 90% 場景首選 Set,有序場景評估 List 成本或「Set + 業務排序字段」方案,慎用 Bag。