6.3.2. 双方向関連

6.3.2. 双方向関連

双方向関連 は関連のどちら「側」からでもナビゲーションできます。2種類の双方向関連がサポートされています:

one-to-many

片側が set か bag 、もう片方が単一値です。

many-to-many

両側が set か bag です。

2つの多対多関連で同じデータベーステーブルをマッピングし、片方を inverse として宣言することで、双方向の多対多関連を指定することが出来ます (どちらを inverse に選んだとしても、そちら側にはインデックス付きのコレクションは使えません)。

次に双方向の多対多関連の例を示します。各カテゴリは多数のアイテムを持つことができ、各アイテムは多くのカテゴリに属することが出来ます。

<class name="Category">
    <id name="id" column="CATEGORY_ID"/>
    ...
    <bag name="items" table="CATEGORY_ITEM">
        <key column="CATEGORY_ID"/>
        <many-to-many class="Item" column="ITEM_ID"/>
    </bag>
</class>

<class name="Item">
    <id name="id" column="CATEGORY_ID"/>
    ...

    <!-- inverse end -->
    <bag name="categories" table="CATEGORY_ITEM" inverse="true">
        <key column="ITEM_ID"/>
        <many-to-many class="Category" column="CATEGORY_ID"/>
    </bag>
</class>

関連の inverse 側にのみ行われた変更は永続化 されません。これは、 Hibernate は全ての双方向関連について、メモリ上に2つの表現を持っているという意味です。つまり一つは A から B へのリンクで、もう一つは B から A へのリンクということです。 Java のオブジェクトモデルについて考え、 Java で双方向関係をどうやって作るかを考えれば、これは理解しやすいです。下記に、 Java での双方向関連を示します。

category.getItems().add(item);          // The category now "knows" about the relationship
item.getCategories().add(category);     // The item now "knows" about the relationship

session.persist(item);                   // The relationship won't be saved!
session.persist(category);               // The relationship will be saved

関連の inverse ではない側は、メモリ上の表現をデータベースに保存するのに使われます。

双方向の一対多関連を定義するには、一対多関連を多対一関連と同じテーブルのカラムにマッピングし、多側に inverse="true" と宣言します。

<class name="Parent">
    <id name="id" column="parent_id"/>
    ....
    <set name="children" inverse="true">
        <key column="parent_id"/>
        <one-to-many class="Child"/>
    </set>
</class>

<class name="Child">
    <id name="id" column="child_id"/>
    ....
    <many-to-one name="parent" 
        class="Parent" 
        column="parent_id"
        not-null="true"/>
</class>

関連の片側に inverse="true" を設定しても、カスケード操作に影響を与えません。これらは直交した概念です。