步步为营Hibernate全攻略(二)剪不断理还乱之:一对多关联映射
一对多关联映射和多对一关联映射的原理是一致的,都是在多的一端加入一个外键,指向一的一端。但是他们又有所区别,有了多指向一的关系,在加载多的时候可以将一加载上来,而有了一对多的关系,在加载一的时候可以将多加载上来。那有了一对多的关联映射,是怎样实现加载一的时候同时加载多呢?要实现这样的功能当然离不开我们配置文件,下面我们就来通过一个小Demo看看如何通过配置文件实现这样的功能。
我们以学生Student和Classes为例,一个班级对应多个学生,每个学生属于一个班级,从班级的角度来看这是一个典型的一对多关系,既然一个班级对应着多个学生,那班级中自然要含有对多个学生的引用,在代码中通常是以集合的形式体现的,来看Student和Classes的具体代码:
<!-- Student.hbm.xml文件 --><?xml version="1.0"?><!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"><hibernate-mapping><class name="com.bjpowernode.hibernate.Student" table="t_student"><id name="id"><generator class="native"/></id><property name="name"/></class></hibernate-mapping>
通过Classes.hbm.xml文件我们可以清楚地看到,Classes类以集合的形式持有对Student的引用,而Student类并不知道Classes的存在。这种一的一端持有多的一端的引用,多的一段不知道一的一端的存在的一对多关联映射形式我们称之为单项关联。但是我们仔细分析一下这种方式单项关联映射存在两个问题:
1. 因为多的一端Student不知道Classes的存在(也就是Student没有维护与Classes的关系)所以在保存Student的时候关系字段classid是为null的,如果将该关系字段设置为空,则将无法保存数据。
2. 另外因为Student不维护关系,而Classes维护关系,classes就会发出多余的update语句,保证classes和Student有关系这样加载Classes的时候才能把该Classes对应得学生加载出来。
解决上面问题的关键就在于将维护classid字段的任务交给Student端来维护,让Student端知道Classes端的存在。这也就是我们最经常用的双向关联。采用双向关联后我们需要在配置文件上做的改动只有两个地方:
1. 在Student.hbm.xml文件中加入<many-to-one name="classes"column="classesid"/>标签,注意一定要让column属性值与Classes.hbm.xml文件中的<key column="classesid" />标签中的column属性值相同,否则会出现数据混乱。
2. 在Classes.hbm.xml文件中的<set name="students" inverse="true">标签中加入inverse="true"属性,inverse 属性可以用在一对多和多队多双向关联上,inverse属性默认为false,为false表示本端可以维护关系 ,如果inverse为true,表示本端不能维护关系,会交给另一端维护关系,本端失效。一对多关联映射我们通常在多的一端维护关系,让一的一端失效,所以设置inverse为true。
通过双向关联实现控制方向上的反转的主要目的是解决一对多单项关联的缺陷而不是需求驱动的。