我们还用上篇博客中贴的图。在Hibernate中有如下7中关联映射。
上篇博客已经将一对一的两种映射类型及不同的实现策略介绍完了。本篇博客继续讨论关联映射中的多对一映射。
一对多关联映射
一)单向多对一关联映射
举例:,用户和组是多对一的关系。一个组有多个用户,一个用户只属于一个组。
实现策略:有了ER图知识的积累,我们知道多对一的关联映射策略一定是在多的一端加入一个外键,指向一的一端。
关键代码:在多的一端加入标签映射。
<hibernate-mapping>
<classname="com.bjpowernode.hibernate.User"table="t_user">
<idname="id">
<generatorclass="native"/>
</id>
<propertyname="name"/>
<many-to-one name="group"column="groupid"cascade="save-update"/>
</class>
</hibernate-mapping>
备注
cascade级联,意思是指定两个对象之间的操作联动关系,对一个对象执行了操作(他是对象之间的连锁操作,只影响添加,删除和修改。)之后,对其指定的级联对象也需要执行相同的操作。可以取值为all,none,save-update,delete。all代表在所有的情况下都执行级联操作。none指在所有情况下都不执行级联操作。save-update指在保存和更新的时候执行级联操作。delete指在删除的时候执行级联操作。
二)单向一对多关联映射
举例 : 班级和学生是一对多的关系。一个班级有多个学生,一个学生只能属于一个班。
实现策略:在多的一端加入一一端的主键当做外键。这样的冗余是最少的。
关键代码 : 在一的一端加入标签映射。
<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>
这是多对一的映射。
备注:
上面我们采用的是在一的一端维护关系。这样的话,多的一端并不知道一的一端的存在。也就是说学生并不知道班级的存在。从代码层级上考虑,在保存学生的时候,关系字段classid是为null的。如果将该字段设置为非空,就不能保存数据了。另外,又由于student并不维护关系,class维护关系,则在对class进行操作时,class就会发出多余的update语句,去维护group与user的关系。可见一对多关联映射存在很大问题。
那么要解决这个问题,我们就要看一下面的一对多双向关联。
三)双向一对多关联映射(重要):
该映射主要是为了解决一对多单向关联的缺陷,并非业务需求导致的。
映射策略:在一的一端的集合上采用标签,并用标签。在多的一端加入一个外键,同时在多的一端采用标签。
主要代码:
student(多的一端)
<many-to-one name="classes" column="classesid"/>
classes(一的一端)
<set name="students"inverse="true">
<key column="classesid"/>
<one-to-many class="com.hibernate.Student"/>
</set>
备注:
其中inverse属性可以用在一对多和多对多双向关联上,inverse属性默认为false,为false表示本端可以维护关系,如果inverse为true,则本端不能维护关系,会交给另一端维护关系,本端失效。所以一对多关联映射我们通常在多的一端维护关系,让一的一端失效。inverse是控制方向上的反转,只影响存储。
总结:
本篇博客介绍了多对一的三种映射关系及其实现策略。包括一对多单向,多对一单项,和一对多双向映射。那么一对多单向映射和多对一的单向映射来说,他们最大的不同是维护的关系不同。
多对一单向维护的是:多指向一的关系,加载多的时候可以将一一起加载上来。
一对多单向维护的是:一指向多的关系,在加载医德时候可以将多加载上来。
一对多双向(也是多对一双向)映射也是为了解决多对一的加载和保存的问题而出现的,在项目开发中,这种双向映射也是非常普遍应用的。
下篇博客中我们继续介绍关联映射之多对多映射。