6.3.2. Bidirectional associations
A
bidirectional association
allows navigation from both "ends" of the association. Two kinds of bidirectional association are supported:
-
one-to-many
-
set or bag valued at one end, single-valued at the other
-
many-to-many
-
set or bag valued at both ends
You may specify a bidirectional many-to-many association simply by mapping two many-to-many associations to the same database table and declaring one end as
inverse
(which one is your choice, but it can not be an indexed collection).
Here's an example of a bidirectional many-to-many association; each category can have many items and each item can be in many categories:
<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>
Changes made only to the inverse end of the association are
not
persisted. This means that Hibernate has two representations in memory for every bidirectional association, one link from A to B and another link from B to A. This is easier to understand if you think about the Java object model and how we create a many-to-many relationship in 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
The non-inverse side is used to save the in-memory representation to the database.
You may define a bidirectional one-to-many association by mapping a one-to-many association to the same table column(s) as a many-to-one association and declaring the many-valued end 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>
Mapping one end of an association with inverse="true"
doesn't affect the operation of cascades, these are orthogonal concepts!