关联关系映射通常情况是最难配置正确的。在这个部分中,我们从单向关系映射开始,然后考虑双向关系映射,由浅至深讲述一遍典型的案例。在所有的例子中,我们都使用 PersonAddress

我们根据映射关系是否涉及连接表以及多样性来划分关联类型。 

 

一、单向关联(Unidirectional associations)一方持有另一方的引用

 

多对一(many to one)

单向many-to-one关联是最常见的单向关联关系。

 
  
  1. <class name="Person"> 
  2.     <id name="id" column="personId"> 
  3.         <generator class="native"/> 
  4.     </id> 
  5.     <many-to-one name="address"  
  6.         column="addressId" 
  7.         not-null="true"/> 
  8. </class> 
  9.  
  10. <class name="Address"> 
  11.     <id name="id" column="addressId"> 
  12.         <generator class="native"/> 
  13.     </id> 
  14. </class> 

多的一方(Person),有一个字段(addressId)指向一的一方(Address)

 

create table Person ( personId bigint not null primary key, addressId bigint not null )
create table Address ( addressId bigint not null primary key )

一对一(one to one)

1、基于外键关联的单向一对一关联单向多对一关联几乎是一样的。

唯一的不同就是单向一对一关联中的外键字段具有唯一性约束。 让多的一方变为 unique即可

 
  
  1. <class name="Person"> 
  2.     <id name="id" column="personId"> 
  3.         <generator class="native"/> 
  4.     </id> 
  5.     <many-to-one name="address"  
  6.         column="addressId"  
  7.         unique="true" 
  8.         not-null="true"/> 
  9. </class> 
  10.  
  11. <class name="Address"> 
  12.     <id name="id" column="addressId"> 
  13.         <generator class="native"/> 
  14.     </id> 
  15. </class> 

 

create table Person ( personId bigint not null primary key, addressId bigint not null unique )
create table Address ( addressId bigint not null primary key )


addressId 为unique,所以只能属于一个 person 
2、 基于主键关联的单向一对一关联 通常使用一个特定的id生成器。(请注意,在这个例子中我们掉换了关联的方向。)( Address 持有Person对象
 
  
  1. <class name="Person"> 
  2.     <id name="id" column="personId"> 
  3.         <generator class="native"/> 
  4.     </id> 
  5. </class> 
  6.  
  7. <class name="Address"> 
  8.     <id name="id" column="personId"> 
  9.         <generator class="foreign"> 
  10.             <param name="property">person</param> 
  11.         </generator> 
  12.     </id> 
  13.     <one-to-one name="person" constrained="true"/> 
  14. </class> 

Address 没有自己的id生成器,只能用 Person类的主键。

create table Person ( personId bigint not null primary key )
create table Address ( personId bigint not null primary key )

一对多(one to many)

1、基于外键关联的单向一对多关联

是一种很少见的情况,并不推荐使用。一对多,需要在一的一方有 set<Address> addresses 属性

 
  
  1. <class name="Person"> 
  2.     <id name="id" column="personId"> 
  3.         <generator class="native"/> 
  4.     </id> 
  5.     <set name="addresses"> 
  6.         <key column="personId"  
  7.             not-null="true"/> 
  8.         <one-to-many class="Address"/> 
  9.     </set> 
  10. </class> 
  11.  
  12. <class name="Address"> 
  13.     <id name="id" column="addressId"> 
  14.         <generator class="native"/> 
  15.     </id> 
  16. </class> 
在多的一方( Address) 增加了一个 指向一方(Person)的列(personId)
create table Person ( personId bigint not null primary key )
create table Address ( addressId bigint not null primary key, personId bigint not null )

我们认为对于这种关联关系最好使用连接表。

注意:列都是增加在多的一方 *-to-many class="**"

二、使用连接表的单向关联

(Unidirectional associations with join tables)

一对多(one to many)

基于连接表的单向一对多关联 应该优先被采用。

请注意,通过指定unique="true",我们可以把多样性从多对多改变为一对多。

(many to one 指定unique=“true”,把多样性从多对一变为一对一

many to many 指定unique=“true”,把多样性从多对多变为 一对多)都把第一个many变为one

 
  
  1. <class name="Person"> 
  2.     <id name="id" column="personId"> 
  3.         <generator class="native"/> 
  4.     </id> 
  5.     <set name="addresses" table="PersonAddress"> 
  6.         <key column="personId"/> 
  7.         <many-to-many column="addressId" 
  8.             unique="true" 
  9.             class="Address"/> 
  10.     </set> 
  11. </class> 
  12.  
  13. <class name="Address"> 
  14.     <id name="id" column="addressId"> 
  15.         <generator class="native"/> 
  16.     </id> 
  17. </class> 

create table Person ( personId bigint not null primary key )
create table PersonAddress ( personId not null, addressId bigint not null primary key )
create table Address ( addressId bigint not null primary key )

多对一(many to one)

1、基于连接表的单向多对一关联

在关联关系可选的情况下应用也很普遍。

 
  
  1. <class name="Person"> 
  2.     <id name="id" column="personId"> 
  3.         <generator class="native"/> 
  4.     </id> 
  5.     <join table="PersonAddress"  
  6.         optional="true"> 
  7.         <key column="personId" unique="true"/> 
  8.         <many-to-one name="address" 
  9.             column="addressId"  
  10.             not-null="true"/> 
  11.     </join> 
  12. </class> 
  13.  
  14. <class name="Address"> 
  15.     <id name="id" column="addressId"> 
  16.         <generator class="native"/> 
  17.     </id> 
  18. </class> 

create table Person ( personId bigint not null primary key )
create table PersonAddress ( personId bigint not null primary key, addressId bigint not null )
create table Address ( addressId bigint not null primary key )

一对一(one to one)

1、基于连接表的单向一对一关联

非常少见,但也是可行的。

 
  
  1. <class name="Person"> 
  2.     <id name="id" column="personId"> 
  3.         <generator class="native"/> 
  4.     </id> 
  5.     <join table="PersonAddress"  
  6.         optional="true"> 
  7.         <key column="personId"  
  8.             unique="true"/> 
  9.         <many-to-one name="address" 
  10.             column="addressId"  
  11.             not-null="true" 
  12.             unique="true"/> 
  13.     </join> 
  14. </class> 
  15.  
  16. <class name="Address"> 
  17.     <id name="id" column="addressId"> 
  18.         <generator class="native"/> 
  19.     </id> 
  20. </class> 

create table Person ( personId bigint not null primary key )
create table PersonAddress ( personId bigint not null primary key, 
                                     addressId bigint not null unique )
create table Address ( addressId bigint not null primary key )

多对多(many to many)

最后,还有 单向多对多关联.

 
  
  1. <class name="Person"> 
  2.     <id name="id" column="personId"> 
  3.         <generator class="native"/> 
  4.     </id> 
  5.     <set name="addresses" table="PersonAddress"> 
  6.         <key column="personId"/> 
  7.         <many-to-many column="addressId" 
  8.             class="Address"/> 
  9.     </set> 
  10. </class> 
  11.  
  12. <class name="Address"> 
  13.     <id name="id" column="addressId"> 
  14.         <generator class="native"/> 
  15.     </id> 
  16. </class> 
create table Person ( personId bigint not null primary key )
create table PersonAddress ( personId bigint not null, 
                                addressId bigint not null, primary key (personId, addressId) )
create table Address ( addressId bigint not null primary key )

总结:

*-to-one 都没有指定 class 属性。*-to-many 都指定了 class 属性

<many-to-one name="address" -->属性
        column="addressId"--->本表中增加 addressId 列
        not-null="true"/> --->不为空
<one-to-one name="person" constrained="true"/> -->Address类中的 person属性


<one-to-many class="Address"/>
<many-to-many column="addressId" <one-to-many>,<many-to-many>都作为set的子元素出现,
因为是 to-many,对多。
    他们都不是在本表中增加字段,要么在多方增加字段(无连接表时(通过<set>中的<key column>
添加),要么在连接表中增加字段(column属性添加))。
    <one-to-many>很少用,只能用在无连接表的 一对多中,有连接表时是<many-to-many>。
    都必须指定class属性,都紧跟着<key>
<many-to-many> 可以指定columu属性,在连接表中可以指定字段名
<one-to-many 依靠key指定属性,只用在无连接表中。
many-to-many 在<set 中指定table名
many-to-one 在<join table> 中指定table名 有连接表时 要么是 <many-to-many> 要么是<many-to-one>,通过增加或取消 unique属性,映射出多对多,一对多; 多对一,一对一;
<many-to-many> 可以对应 多对多,还可以对应 一对多。

<many-to-one> 可以对应 多对一,还可以对应 一对一。
有连接表 都有 <key column="" > 指定一个列名