上一篇博客为大家讲了hibernate中的关联映射,还有一对一关系的两种实现方式,今天为大家说一下多对一的映射关系。
举个例子:一个班级可以有多个学生,而一个学生只能有在一个班级,而这样班级和学生就是一对多的关系,学生和班级就是多对一的关系,下边我们来看一下他们是如何实现这两种关系的。本片博客介绍多对一的关系。
多对一的关系
就是多个学生对应一个班级,我们看一下两个pojo类,
public class Grade {
// 主键
private int gradeID;
// 班级名称
private String gradeName;
// 班级编号
private String gradeNo;
public int getGradeID() {
return gradeID;
}
public void setGradeID(int gradeID) {
this.gradeID = gradeID;
}
public String getGradeName() {
return gradeName;
}
public void setGradeName(String gradeName) {
this.gradeName = gradeName;
}
public String getGradeNo() {
return gradeNo;
}
public void setGradeNo(String gradeNo) {
this.gradeNo = gradeNo;
}
}
public class Student {
// 主键
private int studentID;
// 学生姓名
private String name;
// 学号
private String studentNo;
// 班级
private Grade grade;
public int getStudentID() {
return studentID;
}
public void setStudentID(int studentID) {
this.studentID = studentID;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getStudentNo() {
return studentNo;
}
public void setStudentNo(String studentNo) {
this.studentNo = studentNo;
}
public Grade getGrade() {
return grade;
}
public void setGrade(Grade grade) {
this.grade = grade;
}
我们在看一下这Grade.hbm.xml和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">
<!-- package 对应实体所在包 -->
<hibernate-mapping package="com.tgb.domain">
<!-- table 为映射到数据库中的表名 , 默认与实体名一致 -->
<class name="Grade" table="t_grade">
<id name="gradeID" type="java.lang.Integer">
<generator class="native"></generator>
</id>
<property name="gradeName" />
<property name="gradeNo" />
</class>
</hibernate-mapping>
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- package 对应实体所在包 -->
<hibernate-mapping package="com.tgb.domain">
<!-- table 为映射到数据库中的表名 , 默认与实体名一致 -->
<class name="Student" table="t_student">
<id name="id" type="java.lang.Integer">
<generator class="native"></generator>
</id>
<property name="Name" />
<property name="studentNo" />
<many-to-one name="grade" column="gradeid" cascade="save-update"></many-to-one>
<!-- cascade 指定两个对象之间的操作联动关系,对一个对象执行了操作之后,对其指定的级联对象也需要执行相同的操作 -->
<!-- all:在所有的情况下都执行级联操作; -->
<!-- none:在所有情况下都不执行级联操作; -->
<!-- save-update:在保存和更新的时候执行级联操作;、 -->
<!-- delete:在删除的时候执行级联操作。 -->
</class>
</hibernate-mapping>
这是最基础的准备工作,多对一映射在对数据进行更改时,会有一些限制。当没有该班级时,添加学生,就会出错,当该班级有学生时,删除该班级也会报错。
这样确实是很繁琐,那么该怎么办呢,我们当然可以按一般的方法来做。添加的时候,先手动添加班级,再添加学生。删除时,先删除所有的学生,再删除班级。但是Hibernate为我们提供了一种便捷的方式——many-to-one。在映射文件hbm.xml中配置后,就是many to one中的cascade="save-update",就可以不用再想那些限制了。Hibernate会自动添加上所引用的数据。
下边看一下测试的代码:
public class test {
/**
* 测试添加student
*/
public void testSave3() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Grade grade = new Grade();
grade.setGradeName("一班");
grade.setGradeNo("1");
Student student1 = new Student();
student1.setName("张三");
student1.setStudentNo("1005001");
student1.setGrade(grade);
Student student2 = new Student();
student2.setName("李四");
student2.setStudentNo("1005002");
student2.setGrade(grade);
// 普通方法 :必须先保存group,再保存user
// 配置了many-to-one 则不用再手动save group了。
// session.save(group);
session.save(student1);
session.save(student2);
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
} finally {
HibernateUtils.closeSession(session);
}
}
}
通过我们测试代码可以看到,这样我们不用单独的保存grade了,我们只要保存学生就行了,hibernate 会自动的关联上班级。
多对一的关系,由多的一端来维护关系,这样在加载多的时候可以先将一加载上来。开发中最长使用的使用方式。