双向关联允许通过关联的任一端访问另外一端。在NHibernate中, 支持两种类型的双向关联:
<set>或者<bag>值在一端, 单独值(非集合)在另外一端
两端都是<set>或<bag>值
请注意NHibernate不支持带有索引的集合(IList,IDictionary或者数组)作为"多"的那一端的双向one-to-many关联,你必须使用集合或者bag映射.
要建立一个双向的多对多关联,只需要映射两个many-to-many关联到同一个数据库表中,并再定义其中的一端为inverse(使用哪一端要根据你的选择)。这里有一个从一个类关联到他自身的many-to-many的双向关联的例子(每一个category都可以有很多items,每一个items可以属于很多categories):
<class name name="NHibernate.Auction.Category, NHibernate.Auction">
<id name="Id" column="ID"/>
...
<bag name="Items" table="CATEGORY_ITEM" lazy="true">
<key column="CATEGORY_ID" />
<many-to-many class="NHibernate.Auction.Category, NHibernate.Auction" column="ITEM_ID" />
</bag>
</class>
<class name="NHibernate.Auction.Item, NHibernate.Auction">
<id name="Id" column="ID" />
![]()
<!-- inverse end -->
<bag name="Categories" table="CATEGORY_ITEM" inverse="true" lazy="true">
<key column="ITEM_ID" />
<many-to-many class="NHibernate.Auction.Category, NHibernate.Auction" column="CATEGORY_ID" />
</bag>
</class>
![]()
如果只对关联的反向端进行了改变,这个改变不会被持久化。 这表示NHibernate为每个双向关联在内存中存在两次表现,一个从A连接到B,另一个从B连接到A。如果你回想一下.NET对象模型,我们是如何在.NET中创建多对多关系的,这可以让你更容易理解:
category.Items.Add( item );
// The category now "knows" about the relationship
item.Categories.Add( category );
// The item now "knows" about the relationship
session.Update( item );
// No effect, nothing will be saved!
session.Update( category );
// The relationship will be saved
![]()
非反向端用于把内存中的表示保存到数据库中。如果两端都进行了改编,我们会进行多余的INSERT/UPDATE,甚至可能得到外键冲突!这一点对双向的一对多关联也是一样的。
要建立一个一对多的双向关联,你可以通过把一个一对多关联,作为一个多对一关联映射到到同一张表的字段上,并且在"多"的那一端定义inverse="true"。
<class name="Eg.Parent, Eg>
<id name="Id" column="id" />
...
<set name="Children" inverse="true" lazy="true">
<key column="parent_id" />
<one-to-many class="Eg.Child, Eg" />
</set>
</class>
<class name="Eg.Child, Eg">
<id name="Id" column="id" />
....
<many-to-one name="Parent" class="Eg.Parent, Eg" column="parent_id" />
</class>
在“一”这一端定义inverse="true"不会影响级联操作,二者是不同的概念!