hibernate关联映射之逐步分析
一对一关联映射(单双向)
1 单向
主要是配置文件上的标签配置
比如对于person和idcard两个pojo类。
Person持有idcard的引用。在person.hbm.xml里,person的主键要来源于idcard类,也就是共享idcard的主键。配置:<id name= "id">
<generatorclass="foreign(而不是原来的native)">
<paramname="property(必须是这个)">idcard(用来关联到person类的idcard属性)</param>
</generator>
</id>
另外主要配置<one-to-one>标签,此标签的作用是指示hibernate怎么加载它的关联对象,默认根据主键加载.
标签name属性是通过person类的idcard,关联到idcard类.
Constrained属性主要声明是外键约束.
<one-to-one name="idcard" constrained ="true">2双向
双向基本上是从单向演化而来.person.hbm.xml不变,在idcard.java里添加person引用,
在idcard.hbm.xml里加入<one-to-one>标签.
<one-to-one name="person"/>二 多对一关联映射(单双向)
1 单向
多对一及其简单.比如两个类,user和group.user为多的一方,group为一的一方,只要多的一方在类中持有一的一方的引用,
并且配置文件即user.hbm.xml里加入
<many-to-onename="group"column="groupid"/>
只这一句话便能建立起单向多对一关联映射.
但是,存储的时候要注意,先存一的一方,再存多的一方.
如果想让hibernate自动帮我们存储一的一方,那么就要修改上面的那句话:
<many-to-onename="group"column="groupid"cascade="all"/>
Cascade的意思是级联操作.有"all,save-update,delete,none",默认为none.
即如果要修改多的一方,那hibernate要先把一的一方改了.
这样我们只操作多的一方的增删查改就行了.2 双向
看下面的一对多就知道,多对一和一对多是相对立的.一对多关联映射利用了多对一关联映射原理
多对一关联映射:在多的一端加入一个外键指向一的一端,它维护的关系是多指向一一对多关联映射:在多的一端加入一个外键指向一的一端,它维护的关系是一指向多
也就是说一对多和多对一的映射策略是一样的,只是站的角度不同
总的来说,在多的一方维护是比较好的.
三 一对多关联映射(单双向)
谁要对,那就在谁类里拿到对方的引用,那就再谁配置文件里配.
1单向
还是两个类,class和student.比起不用映射而言,student.hbm.xml不变,class.hbm.xml里多了的是:
<setname="students">
<keycolumn="classesid"/>
<one-to-manyclass="Student"/>
</set>
分析一下,用set标签的出发点是因为class类里持有student的引用(一个set集合),至于为什么是集合而不是如以往的一个student直观的引用,是因为外键要设的不只是一个.如果不能理解,就直接理解为必须用
set标签就成了.
那么name属性是拿到引用,子标签key的column属性是在student里加一个字段,名字叫classesid,
而one-to-many标签是指向student类.
如果<hibernate-mappingpackage="com.bjsxt.hibernate">这样写,
那么在one-to-many标签直接跟类名.
需要注意的是,此时的one-to-many标签里不再像以前的one-to-one标签里用的是name属性而是class属性.这两个属性的功能要分清楚.
单向一对多有缺点,因为要在一的一端维护,所以多的一段的表里的外键字段不可设为非空.而且要发出多余的update语句.一般都设为双向的.下面来看双向.
2双向
双向配置的话class.hbm.xml不变,在student类里持有class类的引用,student.hbm.xml文件配置添加:<many-to-one name="classes" column="classesid(必须和class.hbm.xml里的<key
column="classesid"/>一致)"/>
这样配置就可以存储.有三种存储方式.这是第一种.因为是一的一端维护,所以多发两条update.步骤是先挨个存student,再存
class.
第二种先存class,把classid字段存到student里,再挨个存student.也就是反转.class.hbm.xml里:
<setname="students"inverse="true">
第三种把classid字段存到student里,不存student.只存class. 也就是反转并级联操作.class.hbm.xml里:<set name="students" inverse="true" cascade="all">
关于存储上,基本上就这三种.无论是一对多还是多对一.个人认为比较麻烦.具体应用的时候可以考虑改进
.多对一的时候,因为站在多的立场,如果不级联,要先存一,把一的数据加到多里的引用,再存多.级联了,因
为不用考虑一的关系,所以只存多.
而一对多的时候,反转不级联,就站在多的立场.也要先存一再存多.反转只是立场转为多对一,所以同上.
反转并级联,也同上.不考虑一.
不反转也不级联,因为站在一的立场,就要先存多.把多加入到一的set集合,再存一.所以呢,立场和先存谁是对立的.
请消化一下以上的总结.下面来看多对多.
四 多对多关联映射(单双向)
1 单向.
多对多涉及到第三方表.hibernate会自动生成.一般权限上会用到,比如RBAC模型.
如以往一样,两个类,user和role.同样,user持有role的引用,是一个set集合.(如前面的一对多)
Role.hbm.xml没有变化,User.hbm.xml里多的是:
<setname="roles"table="t_user_role">
<keycolumn="userid"/>
<many-to-manyclass="com.bjsxt.hibernate.Role"column="roleid"/>
</set>
分析一下,set标签不用多说,table属性是指让hibernate自动建立第三方表名字叫"t_user_role",key标签是指在此表中生成一个关联到本类(user的)叫userid的字段,<many-to-many>标签里class属性引入类Role,并在t_user_role里生成一个关联到role的roleid字段.
在t_user_role表里,userid和roleid一并叫做复合主键.因为两者的联合有不可重复性.
其存储流程:1,存入role,2,用一个set集合接住role放到user的set里,(这里交叉存入比较容易看晕)3,挨
个存user.与上面的第二种存储方案差不多.
Load时候就简单,加载进来,在user里用一个遍历挨个从set里拿出来.就得到role表里的值.
执行存入的时候,hibernate就把表t_user_role各个值赋予了.2 双向
基本上与单向一致.
Role里要持有user的引用,也是set集合,
Role.hbm.xml和user.hbm.xml配置差不多.
<setname="users"table="t_user_role"order-by="userid">
<keycolumn="roleid"/>
<many-to-manyclass="com.bjsxt.hibernate.User"column="userid"/>
</set>
注意两类对比,保持column属性值一致.table属性值必须和单向关联中的table属性值一致
<key>中column属性值要与单向关联中的<many-to-many>标签中的column属性值一致
在<many-to-many>中的column属性值要与单向关联中<key>标签的column属性值一致order-by="userid"属性是用来排序,按照t_user_role表的字段来排.
基本上,hibernate映射关系就是这些了.