攻城狮在路上(壹) Hibernate(十一)--- 映射实体关联关系

时间:2023-03-10 02:26:42
攻城狮在路上(壹) Hibernate(十一)--- 映射实体关联关系

本文以Customer和Address类的关系为例说明一对一关联映射;以Category和Item类的关系说明多对多关联关系。
一、映射一对一关联
  分两种情况:按照外键映射和按照主键映射。这两种方式的区别在于对应表结构的不同。
  1、按照外键映射
  实例代码:
Customer.hbm.xml:

<many-to-one name="homeAddress"
  class="mypack.Address"
  column="HOME_ADDRESS_ID"
  cascade="all"
  unique="true"/>

Address.hbm.xml:

<one-to-one name="customer"
  class="mypack.Customer"
  property-ref="homeAddress"/>

参数说明:
unique:该属性表明每个Customer对象都有唯一的homeAddress对象,可以表达这两个对象之间的一对一关联关系。
property-ref:建立了从homeAddress到Customer对象的关联。

其他说明:
所谓的按照外键映射,是指Customer类中建立了到Address的外键homeAddress,通过customer.homeAddress.id导航过去。
在Customer持久化类中,定义了一个Address对象。
  2、按照主键映射:在项目中一般是使用这种配置方式。
实例代码:
Customer.hbm.xml:

<one-to-one name="address"
  class="mypack.Address"
  cascade="all" />

Address.hbm.xml:

<hibernate-mapping >

  <class name="mypack.Address" table="ADDRESSES" >
    <id name="id" type="long" column="ID">
      <generator class="foreign">
        <param name="property">customer</param>
      </generator>
    </id>
    ...
    <one-to-one name="customer"
      class="mypack.Customer"
      constrained="true"/>
  </class>
</hibernate-mapping>  

参数说明:
constrained属性设置为TRUE,表明Address表的id主键同时作为外键参照CUSTOMERS表。所以必须按上面的方式配置标识符生成策略。

二、映射单向多对多关联
假定仅在Category类一端中定义了集合类型的items属性。可以使用<set><list><idbag><map>。
实例代码:

<set name="items" table="CATEGORY_ITEM"
  lazy="true"
  cascade="save-update">
  <key column="CATEGORY_ID" />
  <many-to-many class="mypack.Item" column="ITEM_ID" />
</set>

注意级联的配置即可。

三、映射双向多对多关联关系
对于双向多对多关联关系,必须把其中一端的inverse属性设置为true。
inverse为true的一端可以使用:set\bag.
inverse为false的一端可以使用:set\list\idbag\map.
1、通用配置方式
实例代码:
Category.hbm.xml:

<set name="items" table="CATEGORY_ITEM"
  lazy="true"
  cascade="save-update">
  <key column="CATEGORY_ID" />
  <many-to-many class="mypack.Item" column="ITEM_ID" />
</set>

Item.hbm.xml:

<set name="categories" table="CATEGORY_ITEM"
  lazy="true"
  inverse="true"
  cascade="save-update">
  <key column="ITEM_ID" />
  <many-to-many class="mypack.Category" column="CATEGORY_ID" />
</set>

2、把多对多关联分解为两个一对多关联:最近的项目中使用的是该方式。
实例代码:
Item.hbm.xml:

<set name="lineItems" lazy="true" inverse="true" cascade="save-update">
  <key column="ITEM_ID" />
  <one-to-many class="mypack.LineItem" />
</set>

Order.hbm.xml:

<set name="lineItems" lazy="true" inverse="true" cascade="save-update">
  <key column="ORDER_ID" />
  <one-to-many class="mypack.LineItem" />
</set>

LineItem.hbm.xml:

<many-to-one name="order" column="ORDER_ID" class="mypack.Order" not-null="true" />
<many-to-one name="item" column="ITEM_ID" class="mypack.Item" not-null="true" />

此种方式需要为中间表建立一个持久化类。