关系映射之多对多
多对多的关系在操作和性能方面都不太理想,所以多对多的映射使用较少,实际使用中最好转换成一对多的对象模型;Hibernate会为我们创建中间表,转换成两个一对多。
经典案例:学生<–>选课,如下将学生选课关系用中间表来关联。
这个案例在我们学习HQL语句的时候也用过,所以这里再简要介绍一下。更多的细节请参考【Hibernate——HQL语句】
三个对象的domain对象以及关系映射文件如下:
- Student对象以及关系映射文件:
package com.gavin.domain;
import java.util.Set;
public class Student {
private int id;
private String name;
private Set<StudentCourse> studentCourseSet;
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<StudentCourse> getStudentCourseSet() {
return studentCourseSet;
}
public void setStudentCourseSet(Set<StudentCourse> studentCourseSet) {
this.studentCourseSet = studentCourseSet;
}
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.gavin.domain.Student" table="student" schema="hibernate">
<id name="id" type="java.lang.Integer" column="id">
<generator class="increment"/>
</id>
<property name="name" column="name" type="java.lang.String"/>
<set name="studentCourseSet">
<key column="sid"></key>
<one-to-many class="com.gavin.domain.StudentCourse"/>
</set>
</class>
</hibernate-mapping>
- Course对象以及关系映射文件:
package com.gavin.domain;
import java.util.Set;
public class Course {
private int id;
private String name;
private Set<StudentCourse> studentCourseSet;
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<StudentCourse> getStudentCourseSet() {
return studentCourseSet;
}
public void setStudentCourseSet(Set<StudentCourse> studentCourseSet) {
this.studentCourseSet = studentCourseSet;
}
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.gavin.domain">
<class name="com.gavin.domain.Course" table="course" schema="hibernate">
<id name="id" column="id" type="java.lang.Integer">
<generator class="increment"/>
</id>
<property name="name" column="name" type="java.lang.String"/>
<set name="studentCourseSet">
<key column="cid"></key>
<one-to-many class="com.gavin.domain.StudentCourse"></one-to-many>
</set>
</class>
</hibernate-mapping>
- StudentCourse对象以及关系映射文件:
package com.gavin.domain;
public class StudentCourse {
private int id;
private Student student;
private Course course;
private int grade;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Student getStudent() {
return student;
}
public void setStudent(Student student) {
this.student = student;
}
public Course getCourse() {
return course;
}
public void setCourse(Course course) {
this.course = course;
}
public int getGrade() {
return grade;
}
public void setGrade(int grade) {
this.grade = grade;
}
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.gavin.domain.StudentCourse" table="studcourse" schema="hibernate">
<id name="id" column="id" type="java.lang.Integer">
<generator class="increment"/>
</id>
<property name="grade" type="java.lang.Integer" column="grade"/>
<many-to-one name="student" column="sid"/>
<many-to-one name="course" column="cid"/>
</class>
</hibernate-mapping>
- 测试代码:
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
Student student = new Student();
student.setName("虾米");
Course course = new Course();
course.setName("数学");
StudentCourse studentCourse = new StudentCourse();
studentCourse.setStudent(student);
studentCourse.setCourse(course);
studentCourse.setGrade(89);
session.save(student);
session.save(course);
session.save(studentCourse);
transaction.commit();
- Hibernate生成的SQL语句为:
Hibernate: drop table if exists course
Hibernate: drop table if exists studcourse
Hibernate: drop table if exists student
Hibernate: create table course (id integer not null, name varchar(255), primary key (id)) engine=MyISAM
Hibernate: create table studcourse (id integer not null, grade integer, sid integer, cid integer, primary key (id)) engine=MyISAM
Hibernate: create table student (id integer not null, name varchar(255), primary key (id)) engine=MyISAM
Hibernate: alter table studcourse add constraint FK3e0p086wyy1y3198jmcl1p07e foreign key (sid) references student (id)
Hibernate: alter table studcourse add constraint FKdxogu0d4je13yayrhem591hvn foreign key (cid) references course (id)
Hibernate: select max(id) from student
Hibernate: select max(id) from course
Hibernate: select max(id) from studcourse
Hibernate: insert into student (name, id) values (?, ?)
Hibernate: insert into course (name, id) values (?, ?)
Hibernate: insert into studcourse (grade, sid, cid, id) values (?, ?, ?, ?)
- 生成的表结构如下: