一、 单向N-1关联
1. 单向N-1关联,比如多个人对应同一个地址,只需从人实体端可以找到对应的地址实体无须关心某个地址的全部住户。
2. 为了让两个持久化类支持这种关联映射,程序应该在N的一端增加一个引用1端的关联实体。如下:
public class Person { ... private Address address; .....}
3. 同时在配置hbm文件的时候又分为无连接表和有连接表(一般的N-1情况下都无需连接表),1端在配置hbm文件时保持普通配置。Person.hbm.xml如下:
<?xml version="1.0" encoding="GBK"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="test">
<class name="Person" table="person_inf">
<id name="id" column="person_id">
<generator class="identity"/>
</id>
<property name="name" type="string"/>
<!-- 1. 无连接表。用于映射N-1关联实体,指定关联实体类为Address,指定外键列名为address_id,并指定级联全部操作 -->
<!-- <many-to-one name="address" cascade="all" class="Address" column="address_id"/> -->
<!-- 2. 使用join元素强制使用连接表 -->
<join table="person_address" >
<!-- 映射连接表中参照本表主键的外键列 -->
<key column="person_id"/>
<!-- 映射连接表中参照关联实体的外键列 -->
<many-to-one name="address" cascade="all" class="Address" column="address_id"/>
</join>
</class>
</hibernate-mapping>
二、单向1-1关联
1. 单向1-1与单向N-1的持久化类没有丝毫区别,如上。
2. 单向1-1与单向N-1的映射配置也非常相似,只需要在<many-to-one>元素增加unique="true"属性,用以表示N的一端唯一即可。
<!-- 1. 基于外键的单向1-1关联。 用于映射1-1关联实体,指定关联实体类为Address 指定外键列名为address_id,并指定级联全部操作 -->
<many-to-one name="address" cascade="all" unique="true" class="Address" column="address_id"/>
<!-- 2. 有连接表的单向1-1关联。使用join元素强制使用连接表 -->
<join table="person_address" >
<!-- 映射连接表中参照本表主键的外键列 -->
<key column="person_id"/>
<!-- 映射连接表中参照关联实体的外键列 -->
<many-to-one name="address" cascade="all" unique="true" class="Address" column="address_id"/>
</join>
<class name="Person" table="person_inf">
<id name="id" column="person_id">
<!-- 3. 基于主键关联的单向1-1关联,主键生成策略是foreign,表明根据关联类的主键来生成该实体的主键 -->
<generator class="foreign">
<!-- 指定引用关联实体的属性名 -->
<param name="property">address</param>
</generator>
</id>
<property name="name" type="string"/>
<!-- 下面映射基于主键的1-1关联 -->
<one-to-one name="address"/>
</class>
三、单向1-N关联
1. 单向1-N关联的持久化发生了变化,持久化类里需要使用集合属性,因为N的一端将以集合形式表现.
private Set<Address> addresses = new HashSet<Address>();//赋值时使用 person.getAddresses().add(address);
2. 在1-N映射集合属性的时候必须为集合元素增加<key>子元素来映射外键列。
<!-- 1. 无连接表的单向1-N。映射集合属性,集合元素是其他持久化实体,没有指定cascade属性 -->
<set name="addresses">
<!-- 指定关联的外键列,Address内不指定此列 -->
<key column="person_id"/>
<!-- 用以映射到关联类属性 -->
<one-to-many class="Address"/>
</set>
<!-- 2.有连接表的单向1-N。 指定连接表的表名-->
<set name="addresses" table="person_address">
<!-- 指定连接表中参照本表记录的外键列名 -->
<key column="person_id" />
<!-- 使用many-to-many来映射1-N关联, 增加unique="true" -->
<many-to-many class="Address" column="address_id" unique="true"/>
</set>
四、单向N-N关联
1. 单向N-N关联和1-N关联的持久化类完全相同,在控制关系的一端增加一个集合属性
2. N-N关联必须使用连接表,N-N关联与有连接表的1-N关联非常相似,只要去掉<many-to-many>元素中的 unique="true"。
五、双向1-N(双向N-1)关联
1. 双向1-N关联和双向N-1关联是完全相同的两种情形,两端都需要增加对关联属性的访问,N的一端增加引用到关联实体的属性,1的一端增加集合属性。
public class Person { ... private Set<Address> addresses = new HashSet<Address>(); .....}
public class Address{ ... private Person person; .....}
2. 无连接表的双向1-N关联
<class name="Person" table="person_inf">
.....................
<!-- 映射集合属性,没有指定cascade属性,inverse指定1端不控制关联关系 -->
<set name="addresses" inverse="true">
<!-- 指定关联的外键列 -->
<key column="person_id"/>
<!-- 用以映射到关联类属性 -->
<one-to-many class="Address"/>
</set>
</class>
<class name="Address" table="address_inf">
................
<!-- 必须指定列名为person_id,与关联实体中key元素的column属性值相同 -->
<many-to-one name="person" class="Person" column="person_id" not-null="true"/>
</class>
3. 有连接表的双向1-N关联
<class name="Person" table="person_inf">
....................
<!-- 映射集合属性,集合元素是其他持久化实体,没有指定cascade属性 -->
<set name="addresses" inverse="true" table="person_address">
<!-- 指定关联的外键列 -->
<key column="person_id"/>
<!-- 用以映射到关联类属性 -->
<many-to-many class="Address" column="address_id" unique="true"/>
</set>
</class>
<class name="Address" table="address_inf">
.........................
<!-- 显式使用join元素确定连接表 -->
<join table="person_address">
<!-- key映射外键列 -->
<key column="address_id"/>
<!-- 使用many-to-one映射N-1关联实体 -->
<many-to-one name="person" column="person_id" not-null="true"/>
</join>
</class>
六、双向N-N关联
1. 双向N-N关联需要两端都使用集合属性,两端都增加对集合属性的访问。
2. 双向N-N关联只能采用连接表来建立实体之间的关系。
<class name="Person" table="person_inf">
....................
<!-- 映射集合属性,集合元素是其他持久化实体,没有指定cascade属性 -->
<set name="addresses" table="person_address">
<!-- 指定关联的外键列 -->
<key column="person_id"/>
<!-- 用以映射到关联类属性 -->
<many-to-many class="Address" column="address_id"/>
</set>
</class>
<class name="Address" table="address_inf">
....................
<!-- 映射集合属性,集合元素是其他持久化实体,没有指定cascade属性 -->
<set name="persons" table="person_address">
<!-- 指定关联的外键列 -->
<key column="address_id"/>
<!-- 用以映射到关联类属性 -->
<many-to-many class="Person" column="person_id"/>
</set>
</class>
七、双向1-1关联
1. 双向1-1关联只需在两个持久化类都增加引用关联实体的属性。
2. 基于外键的双向1-1关联
<class name="Person" table="person_inf">
....................
<!-- one-to-one元素映射关联属性,外键列在对方的表内,property-ref指定引用关联类的属性。
即:在address属性所属的Address类内, 必须有person属性的setter和getter方法 -->
<one-to-one name="address" property-ref="person"/>
</class>
<class name="Address" table="address_inf">
.....................
<!-- 使用many-to-one映射1-1关联实体,unique="true"确定为1-1-->
<many-to-one name="person" unique="true" column="person_id" not-null="true"/>
</class>
2. 基于主键的双向1-1关联
<class name="Person" table="person_inf">
....................
<one-to-one name="address"/>
</class>
<class name="Address" table="address_inf">
<id name="addressId" column="address_id">
<!-- 指定foreign主键生成器策略-->
<generator class="foreign">
<!-- 指定该主键值将根据person属性引用的 关联实体的主键来生成-->
<param name="property">person</param>
</generator>
</id>
....................
<!-- 用于映射关联实体 -->
<one-to-one name="person"/>
</class>
3. 有连接表的双向1-1关联
<class name="Person" table="person_inf">
.....................
<!-- 使用join元素强制使用连接表 -->
<join table="person_address" inverse="true">
<!-- 映射连接表中参照本实体主键的外键列 -->
<key column="person_id" unique="true"/>
<!-- 映射1-1关联实体 -->
<many-to-one name="address" class="Address" column="address_id" unique="true"/>
</join>
</class>
<class name="Address" table="address_inf">
............................
<!-- 使用join元素强制使用连接表 -->
<join table="person_address" optional="true">
<!-- 映射连接表中参照本实体主键的外键列 -->
<key column="address_id" unique="true"/>
<!-- 映射1-1关联实体 -->
<many-to-one name="person" class="Person" column="person_id" unique="true"/>
</join>
</class>