您的位置:首页 > 其它

hibernate的多对一,一对多单向关联,双向关联区别与联系

2013-12-13 09:00 337 查看
首先来看一下多对一。举个例子来说用户和组。一个组中有多个用户,一个用户只能属于一组。用户和组之间就是一个多对一的关系的。如下图



这个关系我们要怎样维护呢?我们想象一下,假如在一的一端维护关系,即在group一端加一个字段userId来标识学生。那设计出来的表格存储数据是这个样子的。



不解释,直接看在多的一端维护关系



不用说,大家就知道在多的一端维护数据冗余要少的多。怎么来解释这个问题呢?大家想一下是多的记少的容易记,还是少的记多的容易记呢?举个例子员工和老板。你说是老板记员工比较容易还是员工记老板比较容易呢?很明显记少的比较容易啊,能维护二者的关系也能减少工作量。hibernate当然也是这么做的。看一下实体和配置文件。这里只显示部分代码。

public class Group {

private int id;

private String name;

*************

省略get,set方法

*************

}

从这里我们可以看出,group并不知道user的存在。

public class User {

private int id;

private String name;

private Group group;

*************

省略get,set方法

*************

}

user中包含group属性,来维持关系。

对应的关系映射文件

Group.hbm.xml

<hibernate-mapping>

<classname="com.bjpowernode.hibernate.Group"table="t_group">

<idname="id">

<generatorclass="native"/>

</id>

<propertyname="name"/>

</class>

</hibernate-mapping>

User.hbm.xml

<hibernate-mapping>

<classname="com.bjpowernode.hibernate.User"table="t_user">

<idname="id">

<generatorclass="native"/>

</id>

<propertyname="name"/>

<!—这里用来维系与group的关系。解释一下cascade级联,意思是指定两个对象之间的操作联动关系,对一个对象执行了操作(他是对象之间的连锁操作,只影响添加,删除和修改。)之后,对其指定的级联对象也需要执行相同的操作。可以取值为all,none,save-update,delete。all代表在所有的情况下都执行级联操作。none指在所有情况下都不执行级联操作。save-update指在保存和更新的时候执行级联操作。delete指在删除的时候执行级联操作。 -->

<many-to-onename="group"column="groupid"cascade="save-update"/>

</class>

</hibernate-mapping>
一对多的实现就是这个样子了,那一对多反过来不就是多对一吗?他们有什么不同呢?一对多关联映射和多对一关联映射的原理确实是一致的,都是在多的一端加入外键,指向一的一端。但是他们也是有区别的。我们先看一下他的实现。我们仍然采用一对多的学生用户举例。

public class Group {

private int id;

private Stringname;

private Set users;

*************

省略get,set方法

*************

}

public class User {

private int id;

private Stringname;

*************

省略get,set方法

*************

}

看一下对应的配置文件又是怎么实现的呢?

Group.hbm.xml

<hibernate-mapping>

<classname="com.bjpowernode.hibernate.Group"table="t_group">

<idname="id">

<generatorclass="native"/>

</id>

<propertyname="name"/>

<set name=”users”>

<key column=”groupId”/>

<one-to-many class="com.bjpowernode.hibernate.User">

</set>

</class>

</hibernate-mapping>
User.hbm.xml

<hibernate-mapping>

<classname="com.bjpowernode.hibernate.User"table="t_user">

<idname="id">

<generatorclass="native"/>

</id>

<propertyname="name"/>

</class>

</hibernate-mapping>

这里面并没有体现出任何与一的一端有关联的字段。一对多的关联最后生成的表格与多对一是一样的。但是他们到底有什么区别呢?多对一的维护关系是多指向一的关系,有了此关系,在加载多的时候可以将一加载上来。即我们查询用户的时候,组也被查询出来了。而一对多的关系,是指在加载一的时候可以将多加载进来。即查询组的时候,用户也被查出来了。他们适用于不同的需求。

刚开始我们说过,不管是一对多还是多对一,都是在多的一端维护关系。从程序的执行状况来解释一下这样做的原因。若在一的一端维护关系,多的一端User并不知道Group的存在。所以在保存User的时候,关系字段groupId是为null的。如果将该关系字段设置为非空,则将无法保存数据。另外因为User不维护关系,Group维护关系,则在对Group进行操作时,Group就会发出多余的update语句,去维持Group与User的关系,这样加载Group的时候才会把该Group对应的学生加载进来。可见一对多关联映射是存在这很大的问题的。那怎么解决这些问题呢?看一下下面的一对多双向关联。

实体类实现

public class Group {

private int id;

private String name;

private Set users;

*************

省略get,set方法

*************

}

public class User {

private int id;

private String name;

private Group group;

*************

省略get,set方法

*************

}

接下来看一下映射文件

group.hbm.xml

<hibernate-mapping>

<classname="com.bjpowernode.hibernate.Group"table="t_group">

<idname="id">

<generatorclass="native"/>

</id>

<propertyname="name"/>

<!—inverse属性他可以用在一对多和多对多双向关联上,inverse默认为false,false表示本端可以维护关系,如果inverse为true,则表示本端不能维护关系,会交给另一端维护关系,本端失效。此处我们让多的一端维护关系,一的一端失效。所以,此处设置为true
-->

<set name=”users” inverse=”true”>

<key column=”groupId”/>

<one-to-many class="com.bjpowernode.hibernate.User">

</set>

</class>

</hibernate-mapping>
User.hbm.xml

<hibernate-mapping>

<classname="com.bjpowernode.hibernate.User"table="t_user">

<idname="id">

<generatorclass="native"/>

</id>

<propertyname="name"/>

<many-to-one name=”groupId”/>

</class>

</hibernate-mapping>

这里要注意many-to-one的值要与key的值保持一致。

通过一对多双向关联映射,我们将关系交给多的一端维护,而且从一的一端也能够看到多的一端。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐