您的位置:首页 > 其它

hibernate系列九:多对多关联配置及案例(一)

2017-11-29 23:29 381 查看
前面已介绍了映射一对多和多对一关联关系的方法,这是软件开发中最常见的关联关系。下面将介绍另一种关联关系的映射:多对多关联。

以Course(课程)与Student(学生)类的关系为例,介绍映射多对多关联。一门课程需要多位学生参与,一位学生可能选修多门课程,构成了课程和学生之间的多对多的关系。Course表(课程)、Student表(学生)如图6.4所示。在关系数据模型中,无法直接表达Course表和 Student表之间的多对多关系,需要创建一个连接表Study(学习表)。它同时参照Course表和Student表,下图显示了这3张表的结构。



Study表以sno字段和cno字段作为联合主键。此外,cno字段作为外键参照Course表,而sno字段作为外键参照Student表。

根据业务需要,可以配置课程和学生的单向多对多关联,也可以配置课程和学生的双向多对多关联。接下来详细讲解这两种配置。

1. 配置单向多对多关联

假定仅建立从CourseBean(课程)类到StudentBean(学生)类的单向多对多关联。在CourseBean类中需要定义集合类型students属性,而在StudentBean类中不需要定义集合类型的courses属性。下图显示了CourseBean类和StudentBean类的关联关系。



在CourseBean类中定义students属性代码如下所示:

public class CourseBean implementsSerializable{

private String cno;

private String cname;

privateSet<StudentBean> students=new HashSet<StudentBean>();

//省略getter和setter方法

}

在CourseBean.hbm.xml文件中,映射CourseBean类的students属性的代码如下所示:

<set
name="students"
table="study"cascade="save-update">
<key
column="cno"></key>
<many-to-many
class="com.beans.student.StudentBean"column="sno"/>
</set>

<set>元素的table属性指定关系表的名称为Study。

<set>元素的cascade属性为“save-update”,表明保存或更新Course对象时,会级联保存或更新与它关联的Student对象。

<set>元素的<key>子元素指定Study的外键cno,用来参照Course表。

<many-to-many>子元素的class属性指定students集合中存放的是StudentBean的对象,column属性指定Study表的外键sno,用来参照Student表。

经验 对于多对多关联,cascade属性设为“save-update"是合理的,但是不建议把cascade属性设为“all”、“delete"。如果删除一个CourseBean对象时,还级联删除与它关联的所有StudentBean对象,由于这些Student对象有可能还与其他CourseBean对象关联,因此当Hibernate执行级联删除时,会违反数据库的外键参照完整性。

基于以上配置,完成以下持久化操作,创建两个CourseBean对象和两个StudentBean对象,建立它们的关联关系,保存CourseBean对象的同时保存StudentBean对象,如示例1所示。

示例1

StudentBeanstudent1=new StudentBean(1101,"张三");
StudentBeanstudent2=new StudentBean(1102,"李四");

CourseBeancourse1=new CourseBean(101,"大学物理");
CourseBeancourse2=new CourseBean(102,"计算机基础");

course1.getStudents.add(student1);
course1.getStudents.add(student2);

course2.getStudents.add(student1);

session.save(course1);
session.save(course2);


下图显示了以上程序建立的CourseBean对象与StudentBean对象的关联关系。



当Session的save()方法保存Coursel对象时,向Course表插入一条记录,同时还会分别向Student和Study表插入两条记录,执行如下insert语句:

insert into Course (cname,cno) values (?,?)

insert into Student (sname,sno) values (?,?)

insertinto Student (sname,sno) values (?,?)

insert into Study (cno,sno) values(?,?)

insert into Study (cno,sno) values(?,?)

当Session的save()方法保存course2对象时,向Course表插入一条记录,同时向Study

表插入一条记录。由于与course2对象关联的student1对象已经被保存到数据库中,因此不再向Student表插入记录。Hibernate执行如下SQL语句:

insertinto Course (cname,cno) values (?,?)

insert into Study (cno,sno) values(?,?)

2 配置双向多对多关联

对于双向多对多关联,需要把其中一端的inverse属性设为true,关联的两端都可以使用<set>元素。假定建立了从CourseBean类到StudentBean类的双向多对多关联。在CourseBean类中需要定义集合类型的students属性,并且在StudentBean类也需要定义集合类型的Courses属性。下图显示了CourseBean类和StudentBean类的关联关系。



在CourseBean.hbm.xml文件中,映射CourseBean类的students属性的代码如下所示:

<set
name="students"
table="study"cascade="save-update">
<key
column="cno"></key>
<many-to-many
class="com.beans.student.StudentBean"column="sno"/>
</set>

在StudentEntityloyee.hbm.xml文件中,映射Ernployee类的CourseBeans属性的代码如下所示:

<set
name="courses"
table="Study"
inverse="true">
<key
column="sno"></key>
<many-to-many
class="com.beans.student.CourseBean"column="cno"/>
</set>

对于双向多对多关联的两端,需要把其中一端的<set>元素的inverse属性设为“true”。在示例14的基础上,使用双向多对多关联完成持久化操作,同时建立从CourseBean到StudentBean和从StudentBean到CourseBean的关联关系,如示例2所示。

示例2

StudentBeanstudent1=new StudentBean(1101,"张三");
StudentBeanstudent2=new StudentBean(1102,"李四");

CourseBeancourse1=new CourseBean(101,"大学物理");
CourseBeancourse2=new CourseBean(102,"计算机基础");

course1.getStudents.add(student1);
course1.getStudents.add(student2);

course2.getStudents.add(student1);

student1.getCourses().add(course2);

session.save(course1);
session.save(course2);


下图显示了以上程序建立的CourseBean对象与StudentBean对象的关联关系。



示例2和示例1的运行结果相似,不再做详细介绍。

经验 在软件开发过程中,根据业务需要,可以把多对多关联分解为两个一对多关联。

具体请参考一下篇博文。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: