以学生课程这个多对多映射为例,每个学生可以选多门课程,而每门课程又可以被多个学生选择。多对多映射可以分为两种:单向的多对多和双向的多对多
一、单向的多对多映射:这里以学生为主,可以查询每个学生选修的多门课程,但是不能查询选修某个课程的学生
1.新建学生类Student:
package com.test.model;
import java.util.HashSet;
import java.util.Set;
public class Student {
private int id;
private String name;
private Set<Course> courses = new HashSet<Course>();
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;
}
public Set<Course> getCourses() {
return courses;
}
public void setCourses(Set<Course> courses) {
this.courses = courses;
}
}
这个类中包括id,学生名称,选修的课程三个属性。
2.新建课程类Course:
package com.test.model;
public class Course {
private int id;
private String name;
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;
}
}
课程类中有id和课程名称两个属性。
3.编写Student的映射文件:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.test.model">
<class name="Student" table="t_student">
<id name="id" column="studentId">
<generator class="native"></generator>
</id>
<property name="name" column="studentName"></property>
<set name="courses" table="student_courses" cascade="save-update">
<key column="student_id"></key>
<many-to-many class="com.test.model.Course" column="course_id"></many-to-many>
</set>
</class>
</hibernate-mapping>
这里重点说一下<set>标签,使用<set>标签定义学生类中的集合元素courses,把这个元素重新成一张新的数据表student_courses,student_courses这个数据表的外键student_id映射t_student表的主键,这个表的外键course_id映射Course类数据表的主键。cascade属性值为save-update表明当保存t_student表中的数据时级联保存student_courses中的数据。
4.编写Course类的映射文件:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.test.model">
<class name="Course" table="t_course">
<id name="id" column="courseId">
<generator class="native"></generator>
</id>
<property name="name" column="courseName"></property>
</class>
</hibernate-mapping>
这个表没啥好说的。
5.把这两个映射文件添加到配置文件中。写测试函数:
@Test
public void testSave1(){
Course course1 = new Course();
course1.setName("语文");
Course course2 = new Course();
course2.setName("数学");
Student student1 = new Student();
student1.setName("张三");
student1.getCourses().add(course1);
student1.getCourses().add(course2);
Student student2 = new Student();
student2.setName("李四");
student2.getCourses().add(course1);
student2.getCourses().add(course2);
session.save(student1);
session.save(student2);
}
@Test
public void testLoad1(){
Student student = (Student)session.get(Student.class, 1);
Set<Course> courses = (Set<Course>) student.getCourses();
Iterator it = courses.iterator();
while(it.hasNext()){
Course c = (Course) it.next();
System.out.println(c.getName());
}
}
运行testSave1方法,生成的数据库表结构为:
生成的表中的数据为:
运行testLoad1方法,查询学号为1的学生选择的课程:
2.双向多对多映射
1.新建学生类Student2:
package com.test.model;
import java.util.HashSet;
import java.util.Set;
public class Student2 {
private int id;
private String name;
private Set<Course2> courses = new HashSet<Course2>();
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;
}
public Set<Course2> getCourses() {
return courses;
}
public void setCourses(Set<Course2> courses) {
this.courses = courses;
}
}
2.新建课程类Course2:
package com.test.model;
import java.util.HashSet;
import java.util.Set;
public class Course2 {
private int id;
private String name;
private Set<Student2> students = new HashSet<Student2>();
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;
}
public Set<Student2> getStudents() {
return students;
}
public void setStudents(Set<Student2> students) {
this.students = students;
}
}
这里为了实现双向查询,课程类中添加了学生类的集合属性。
3.编写学生类映射文件:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.test.model">
<class name="Student2" table="t_student2">
<id name="id" column="studentId">
<generator class="native"></generator>
</id>
<property name="name" column="studentName"></property>
<set name="courses" table="student_courses2" cascade="save-update">
<key column="student_id"></key>
<many-to-many class="com.test.model.Course2" column="course_id"></many-to-many>
</set>
</class>
</hibernate-mapping>
4.编写课程类映射文件:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.test.model">
<class name="Course2" table="t_course2">
<id name="id" column="courseId">
<generator class="native"></generator>
</id>
<property name="name" column="courseName"></property>
<set name="students" table="student_courses2" inverse="true">
<key column="course_id"></key>
<many-to-many class="com.test.model.Student2" column="student_id"></many-to-many>
</set>
</class>
</hibernate-mapping>
这里<set>标签中设置了inverse的值为true,这表示又学生类一端来维护表关系。
5.以上两个映射文件添加到配置文件中,写测试方法:
@Test
public void testSave2(){
Course2 course1 = new Course2();
course1.setName("语文");
Course2 course2 = new Course2();
course2.setName("数学");
Student2 student1 = new Student2();
student1.setName("张三");
student1.getCourses().add(course1);
student1.getCourses().add(course2);
Student2 student2 = new Student2();
student2.setName("李四");
student2.getCourses().add(course1);
student2.getCourses().add(course2);
session.save(student1);
session.save(student2);
}
@Test
public void testLoad2(){
Course2 course = (Course2) session.get(Course2.class, 1);
Set<Student2> students = (Set<Student2>)course.getStudents();
Iterator it = students.iterator();
while(it.hasNext()){
Student2 s = (Student2) it.next();
System.out.println(s.getName());
}
}
运行testSave2方法,生成的表结构为:
生成的数据为:
运行testLoad2方法,查询选择了语文课程的学生: