Hibernate关联映射及配置

  ORM,即对象关系映射,其中对象指应用程序中的实体对象,关系指关系型数据库。 ORM框架的核心功能,就是 通过操作对象的方式来隐性操作数据库。Hibernate作为一个经典的ORM框架,已经封装了底层的数据库操作,而开发人员只需要做好对象之间的关联关系映射,就能简单地通过操作对象来实现数据库的更新。
  对象之间存在多种关联关系,而且大部分关联关系在Hibernate中都有不止一种映射方式。在重温了Hibernate的七种关联关系映射后,我简单地做了一些总结,错误之处恳请大牛指正!

0 必须知道的前置条件
  0.1 应用程序中的实体类对应数据库中的表,实体类的属性对应表中的字段。
  0.2 关联关系是对对象而言的,而不是数据库。分析对象之间的关联关系,目的就是要将这种关系映射到数据库中。
  0.3 对象模型的关联关系存在方向性的说法,即从不同的方向分析两个对象的关系,其结果是不同的。
  0.4 关联关系的方向是人为约定的,并不是对象之间固有的。

1 单向关联映射
  如果用X、Y分别代表一或多,那么X对Y的单向关联关系就是,找到了X就能找到Y(前提是Y已经存在),而反过来则不行,找到Y后是发现不了X的。
  单向关联关系可以概括为:前者依赖于后者,关联关系由前者维护,对后者透明。由于Y对关联关系透明,所以Y只要把自己的属性映射到数据库表就行了,而X不仅要把自己的属性映射到数据库表,还要把X和Y之间的关联关系也映射到数据库表中。

1.1 多对一单向关联映射
  以学生和班级为例,多个Student对应一个Classs(注意class是关键字,这里用了3个s),方向从Student到Classs,Student知道自己的班级,而Classs不知道自己班的学生。
  映射原理 :在多方(Student)中加入一个对一方(Classs)的引用。对于数据库表来说,就是在多方加外键。
  映射方式 :在Student类中加一个对关联对象的引用classs,然后在Student.hbm.xml中加入many-to-one的映射配置:
 
 


1.2 一对一单向关联映射
  以学生和座位为例,一个Student只对应一个Seat,方向从Student到Seat,Student知道自己的座位,而Seat不知道对应的学生。
  一对一单向关联有两种映射方式:唯一外键关联和主键关联。
1.2.1 唯一外键关联
  在多对一单向关联映射的基础上,对外键加唯一性约束,就变成了一对一单向关联映射。一对一是多对一的一种特殊情况。
  映射原理 :在前者(Student)加入一个对后者(Seat)的引用。对于数据库表来说,就是在前者加唯一外键。
  映射方式 :在Student类中加一个对关联对象的引用seat,然后在Student.hbm.xml中加入many-to-one的配置,并用unique做约束:
 
 


1.2.2 主键关联(存在局限性)
  如果Student和Seat的主键保持一致,那么它们也是一对一的关联关系。
  接下来就是对谁的主键进行约束的问题了。从Student到Seat的单向关联,关联关系由Student维护,所以Student需要持有对Seat的引用,可以理解为Seat是Student的一部分。当存储Student的时候Seat应该已经存在,即Seat的主键已经生成,而Student和Seat的主键又是相同的,所以Student的主键只能参照Seat的主键来生成。
  映射原理 在前者(Student)加入一个对后者(Seat)的引用,并 保持它们的主键一致,前者(Student)主键参照后者(Seat)主键。
  映射方式 :在Student类中加一个对关联对象的引用seat,然后在Student.hbm.xml中将主键生成策略设为foriegn,并加入one-to-one的映射配置,用constraned限制其唯一性:

 
  
  
   
   seat
  
 
 
 
 


  PS: 主键映射存在缺陷,扩展性差,当对象之间的关系发生改变时,需要同时维护两个对象,因此,非特殊情况下,一般不采用共同主键来做一对一关联映射。

1.3 一对多单向关联映射(存在局限性)
  以班级和学生为例,一个Classs对应多个Student,方向从Classs到Student,Classs知道自己班的学生,而Student不知道自己的班级。
  可以看出,一对多其实是多对一的逆向,只是分析的角度不同,映射原理是类似的。
  映射原理 :在一方(Classs)加入一个对多方(Student)集合的引用。对数据库表而言,同样是在多方加外键。
  映射方式 :在Classs类中加一个关联对象集合的引用students,然后在Classs.hbm.xml中加入set的配置:
 
  
  
  
  
  
 


  PS1: 这种一对多单向关联映射存在问题 。由于关联关系由Classs来维护,Classs通过往t_student加外键的方式来做对象关联。这么一来Student对应的表就有一个classs_id字段,由于关联方向的问题,Student并不知道Classs的存在。因此,当存储Student时是无法为t_student中的外键classs_id赋值的,而外键一般是非空的,这样就会导致Student无法存储。所以, 一对多单向关联映射一般将其转换为一对多/多对一双向关联映射,然后由多方(Student)来维护关系。 参考2.1。
  PS2:一对多单向关联映射也可以通过连接表来实现,即 把一对多看成是多对多的一种特殊情况,通过限制多对多的唯一性来转换成一对多。 参考1.4。

1.4 多对多单向关联映射
  以学生和课程为例,一个Student有多个Course,一个Course有多个Student,方向从Student到Course,Student知道自己选了哪些课程,而Course不知道有哪些学生选了该课程。
  多对多单向关联映射与之前的几种不太一样,仅仅通过外键关联无法实现映射,必须借助连接表来完成,把Student和Course的关联关系一一放到连接表中。
  映射原理 :通过连接表来存放关联关系。
  映射方式 :在Student类中加一个对关联对象集合的引用courses,然后在Student.hbm.xml中加入set的配置,如果对many-to-one加唯一限制将会转换成一对多关联映射:
 
 
  
  
  
   
 


  PS:这种连接表只是单纯地表达Student和Course之间的关系,如果想要知道哪个学生哪门课的成绩,就需要用一个类似成绩单的实体来映射成连接表。

2 双向关联映射
  双向关联映射都是在单向关联映射的基础上完成的,理解了单向关联,双向关联也就很好理解了。

2.1 一对多/多对一双向关联映射
  1.3中的一对多单向关联映射存在局限性,一般是由单向关联转换为双向关联,由多方来维护关联关系。
  基于1.3的映射,在 Student类中加一个对关联对象的引用classs,然后在Student.hbm.xml中加入many-to-one的映射配置,必须保证Student.hbm.xml中many-to-one的column属性与Classs.hbm.xml中key的column属性一致:
 
 


2.2 一对一双向关联映射
  分两种映射方式来说,以单向为基础进行补充。相同点都是在 Seat类加一个对关联对象的引用student,不同点在于映射文件的配置。
2.2.1 唯一外键关联(双向关联)
  在Seat.hbm.xml中加入one-to-one的配置,通过property-ref属性来指定关联关系:
 
 


2.2.2 主键关联(双向关联)
  在Seat.hbm.xml中加入one-to-one的配置。


2.3 多对多双向关联映射
  多对多双向关联映射,其实就是两个方向的多对多单向关联映射相加的结果。由于多对多采用连接表来映射对象之间的关联关系,除此之外对象之间没有其他直接关联,所以可以简单地看成这两个对象是关于连接表对称的。因此,我们只需要将多对多单向关联映射做的事情,在另一个方向再做一次,就能实现多对多的双向关联。
  基于1.4的映射, 在Course类中加一个关联对象集合Set的引用students,然后在Course.hbm.xml中加入set的配置,必须保证Course.hbm.xml和Student.hbm.xml中连接表的表名和字段名完全一致。
 
 
  
  
  
   
 


你可能感兴趣的:(Hibernate)