Hibernate 与拥有的复合元素集合的双向关系

Hibernate bidirectional relationship with owned collection of composite-elements

我想在两个实体之间创建一个非常 classic 的双向父子关系。代码:

public class History {
    public Long id;
    public List<HistoryField> fields;
}

public class HistoryField {
    public History history;
    public String foo, bar;
}

HistoryField 归其 History 父级所有。

为了对此建模,我使用了以下休眠映射:

<class name="History" table="history">
    <id name="id" type="long" />
    <list name="fields" cascade="all" table="fields">
        <key column="history_id" />
        <list-index column="order_index" />
        <composite-element class="HistoryField">
            <property name="foo" />
            <property name="bar" />
        </composite-element>
    </list>
</class>

但是如何在 HistoryField::history 之间的 link 到拥有实体 History 的映射中指定

这里的诀窍是集合是拥有的,并定义为复合元素([=12= 没有 ID,主键是对 history_id + order_index).双向父子关系的经典例子在这里不适用;因为他们解释了两个具有 ID 的 class 之间的关系,而这里拥有的 class 没有 ID。

文档指出您可以为 <component/> 定义一个 <parent/> 元素,虽然它没有在 <composite-element/> 指定的组件集合的上下文中明确提及这一点我想它应该可以工作。

https://docs.jboss.org/hibernate/orm/3.3/reference/en/html/components.html

The <component> element allows a <parent> subelement that maps a property of the component class as a reference back to the containing entity.

因此:

<class name="History" table="history">
    <id name="id" type="long" />
    <list name="fields" cascade="all" table="fields">
        <key column="history_id" />
        <list-index column="order_index" />
        <composite-element class="HistoryField">
            <!-- name of the property refeencing the containing entity -->
            <parent name="history"/>
            <property name="foo" />
            <property name="bar" />
        </composite-element>
    </list>
</class>

当使用注释时,@Parent 注释可以类似地使用:

https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/Hibernate_User_Guide.html#mapping-Parent

The Hibernate-specific @Parent annotation allows you to reference the owner entity from within an embeddable.

@Embeddable
public class HistoryField {

    @Parent
    public History history;
    public String foo, bar;
}