hibernate关联映射之逐步分析

无道圣教主 2010-11-04

一对一关联映射(单双向)

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映射关系就是这些了.

相关推荐

LetonLIU / 0评论 2020-05-29
东方咖啡屋 / 0评论 2020-01-06