今天继续来看hibernate的另一种关联关系,一对多关联。本文以班级(Classes)和(Student)为例进行讲述。
1.原理
先看原理图:
可见,一对多和多对一的映射原理是相同的,都是在多的一方加了一个外键,指向一的一方。
2.基于xml文件的映射配置
Student类的源代码:
public class Student {
private int id;
private String name;
//省略getter和setter
}
Student的映射配置文件:
<hibernate-mapping>
<class name="Student" table="t_student">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
</class>
</hibernate-mapping>
Classes类的代码:
public class Classes {
private int id;
private String name;
//维护关系的是Classes方,它持有多个Student,也可以使用List来定义
private Set students;
//省略getter和setter
}
Classes类对应的映射文件:
<hibernate-mapping>
<class name="Classes" table="t_classes">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<!--一对多配置-->
<set name="students">
<key column="classesid"/>
<one-to-many class="Student"/>
</set>
</class>
</hibernate-mapping>
下面来测试一下:
@Test
public void testSave1() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Student student1 = new Student();
student1.setName("张三");
session.save(student1);
Student student2 = new Student();
student2.setName("李四");
session.save(student2);
Classes classes = new Classes();
classes.setName("中一班");
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);
}
}
运行完成后hibernate,hibernate的日志:
Hibernate: insert into t_student (name) values (?)
Hibernate: insert into t_student (name) values (?)
Hibernate: insert into t_classes (name) values (?)
Hibernate: update t_student set classesid=? where id=?
Hibernate: update t_student set classesid=? where id=?
可以看到,发出了两条update语句。由于维护关系的一方是Classes,导致Student一方不知道Classes的存在,所以在保存Student的时候关系字段classesid是为null的,如果将该关系字段设置为非空,则将无法保存数据。另外因为Student不维护关系,而Classes维护关系,Classes就会发出多余的update语句,保证Classes和Student有关系,这样加载Classes的时候才可以把该Classes对应的学生加载上来。
实际开发中,都将一对多做成双向的,让多的一方来维护。