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

来源:互联网 发布:淘宝网中老年棉皮鞋 编辑:程序博客网 时间:2024/06/14 23:23

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

以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">

     <keycolumn="cno"></key>

     <many-to-manyclass="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">

     <keycolumn="cno"></key>

     <many-to-manyclass="com.beans.student.StudentBean"column="sno"/>

 </set>

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

<set name="courses" table="Study" inverse="true">

     <keycolumn="sno"></key>

     <many-to-manyclass="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的运行结果相似,不再做详细介绍。

 

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

 具体请参考一下篇博文。

原创粉丝点击