上篇文章讨论了双向关联的一对一映射,用了两个章节,主要是从主键和外键两种关联映射展开详细讨论,双向关联的映射需要在两个映射文件中分别添加相互的对应关系,斌刚在相应的类中添加对应的关联类的属性,这样在一端加载时才能加载到另一端的对象。关联中常用的主要有多对一、一对一、一对多和多对多,我们已经讨论了两种映射关系,接下来将会讨论一对多的关系。
一、单向一对多
前篇文章中曾经对多对一的关系展开了讨论,其中主要使用的是
对象模型说明了这种一对多的关系是由一的一端来维护的,那么映射成关系模型就是一个班级字段下面会有多个学生,这样就形成了一对多的关系,通过班级能够查询获得学生信息,对应的关系模型如下图:
1、基本配置
有了对象模型接下来就让它们映射为对应的关系代码,在进行关系映射时需要在一的一端添加
Classes类及映射文件 它是模型中最重要的一端,在该端需要添加对应的set属性,并在配置文件中添加set标签,在set标签中配置相应的
package com.src.hibernate; import java.util.Set; public class Classes { private int id; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } private String name; //Set支持延迟加载 private Set students; public Set getStudents() { return students; } public void setStudents(Set students) { this.students = students; } }
Classes对象中使用了set属性,但是只是说明了延迟加载的属性,并没有为属性配置对应的对象,属性的对象是要在映射文件中来配置的,需要添加set标签,并在set标签中添加
对应的Student对象中的代码和映射文件不需要什么特殊的配置,只需要按照通常的写法编写即可,具体的配置方法不再详述,很简单。配置好后需要生成对应的SQL语句,将对象模型转化为关系模型时Hibernate生成相应的语句如下:
alter table t_student drop foreign key FK4B9075705E0AFEFE drop table if exists t_classes drop table if exists t_student create table t_classes (id integer not null auto_increment, name varchar(255), primary key (id)) create table t_student (id integer not null auto_increment, name varchar(255), classesid integer, primary key (id)) alter table t_student add index FK4B9075705E0AFEFE (classesid), add constraint FK4B9075705E0AFEFE foreign key (classesid) references t_classes (id)
对比SQL语句和关系模型,相应的表之间的关联是通过外键来维护的,首先是创建两张表,并指定表的主键,最后添加一对多的外键关联关系。
2、基本操作
在对 数据库的操作无非是读和写两种,修改也属于写的一种,接下来看看是如何向数据库中写入和读取操作的。写入数据 写入数据需要注意的是一对多的关系,所以在添加的时候需要添加多个学生类,另外由于在classes中添加了对应的set属性,所以在添加Student对象时应该使用HashSet来添加,这样既可实现一对多的关系,具体如下代码:
public void testSave2(){
Session session=null;
try{
session=HibernateUtils.getSession();
session.beginTransaction();
Student student1=new Student();
student1.setName("zhangsan");
session.save(student1);
Student student2=new Student();
student2.setName("lisi");
session.save(student2);
Classes classes=new Classes();
classes.setName("ClassOne");
Set students=new HashSet();
students.add(student1);
students.add(student2);
classes.setStudents(students);
//可以成功保存数据
//但是会发出多余的update语句来维持关系,因为是一对多的原因
session.save(classes);
session.getTransaction().commit();
}catch(Exception e){
e.printStackTrace();
session.getTransaction().rollback();
}finally{
HibernateUtils.closeSession(session);
}
}
那么运行上面的测试用例生成的对应的数据写入到数据库中后如下图:
读取数据 写入操作相对简单,只需要把所有加载的对象都添加到Transient状态下,运行相应的方法就可以插入内容,但是对应的读取操作就会稍微复杂点,因为需要迭代获取所有的学生对象,所以这种一对多的关系效率并不很高,具体代码如下:
package com.test.hibernate; import java.util.Iterator; import java.util.