【SSH高速進階】——Hibernate 多對多映射
說到多對多關系。印象最深刻的就是大學的選修課。一個學生能夠選修多門課程,一門課程能夠有多個學生選修,學生所選的每一門課程還有成績。
這個場景的E-R圖例如以下:
對於多對多的關系,我們一般會抽出一張中間表(連接表),來負責維護這兩張表的多對多關系。比方上述關系應該生成的表結構為:
PO對象
Student.java
public class Student {
private int id;
private String name;
private Set<Course> courses;
//getter、setter
}
Course.java
public class Course {
private int id;
private String name;
private Set<Student> students;
//getter、setter
}
映射文件
Student.hbm.xml
<hibernate-mapping package="org.hibernate.test">
<class name="com.danny.hibernate.Student" table="t_student">
<id name="id">
<generator class="native" />
</id>
<property name="name" />
<set name="courses" table="t_signup">
<key column="student_id"></key>
<many-to-many class="com.bjpowernode.hibernate.Course" column="course_id" ></many-to-many>
</set>
</class>
</hibernate-mapping>
Course.hbm.xml
<hibernate-mapping package="org.hibernate.test">
<class name="com.danny.hibernate.Course" table="t_course">
<id name="id">
<generator class="native" />
</id>
<property name="name" />
<set name="students" table="t_signup" inverse="true">
<key column="course_id"></key>
<many-to-many class="com.bjpowernode.hibernate.Student" column="student_id"></many-to-many>
</set>
</class>
</hibernate-mapping>
配置文件裏的set相應於相應類中的集合,key是指向多的一方的外鍵,相應t_score表中的course_id。
執行代碼執行的建表語句為:
alter table t_signup drop foreign key FK7DADC3438FFF3382
alter table t_signup drop foreign key FK7DADC3438CBEF332
drop table if exists t_course
drop table if exists t_signup
drop table if exists t_student
create table t_course (id integer not null auto_increment, name varchar(255), primary key (id))
create table t_signup (student_id integer not null, course_id integer not null, primary key (student_id, course_id))
create table t_student (id integer not null auto_increment, name varchar(255), primary key (id))
alter table t_signup add index FK7DADC3438FFF3382 (student_id), add constraint FK7DADC3438FFF3382 foreign key (student_id) references t_student (id)
alter table t_signup add index FK7DADC3438CBEF332 (course_id), add constraint FK7DADC3438CBEF332 foreign key (course_id) references t_course (id)
生成的表結構例如以下:
t_signup中生成了復合主鍵,student_id和course_id各自是指向t_student和t_course的外鍵。
插入測試
session.beginTransaction();
Course course1=new Course();
course1.setName("《心理應激微反應》");
session.save(course1);
Course course2=new Course();
course2.setName("《哈利·波特與遺傳學》");
session.save(course2);
Course course3=new Course();
course3.setName("《三國殺攻略教程》");
session.save(course3);
Course course4=new Course();
course4.setName("《寄生蟲與寄生蟲病視頻贊賞》");
session.save(course4);
Student student1=new Student();
Set courses1=new HashSet();
courses1.add(course1);
courses1.add(course2);
student1.setCourses(courses1);
student1.setName("小胡");
session.save(student1);
Student student2=new Student();
Set courses2=new HashSet();
courses2.add(course3);
courses2.add(course4);
student2.setCourses(courses2);
student2.setName("小玉");
session.save(student2);
Student student3=new Student();
Set courses3=new HashSet();
courses3.add(course1);
courses3.add(course2);
courses3.add(course3);
courses3.add(course4);
student3.setCourses(courses3);
student3.setName("小洋");
session.save(student3);
session.getTransaction().commit();
插入結果:
查詢測試(上述配置是雙向關聯)
查詢課程以及選修該課程的全部學生
session.beginTransaction();
Course course=(Course)session.load(Course.class, 1);
System.out.println("-"+course.getName());
for(Student s:course.getStudents()){
System.out.println("--"+s.getName());
}
session.getTransaction().commit();
查詢結果:
Hibernate: select course0_.id as id2_0_, course0_.name as name2_0_ from t_course course0_ where course0_.id=?
-《心理應激微反應》
Hibernate: select students0_.course_id as course2_1_, students0_.student_id as student1_1_, student1_.id as id0_0_, student1_.name as name0_0_ from t_signup students0_ left outer join t_student student1_ on students0_.student_id=student1_.id where students0_.course_id=?
--小胡
--小洋
查詢學生以及該學生所選修的全部課程
session.beginTransaction();
Course course=(Course)session.load(Course.class, 1);
System.out.println("-"+course.getName());
for(Student s:course.getStudents()){
System.out.println("--"+s.getName());
}
session.getTransaction().commit();
查詢結果
Hibernate: select student0_.id as id0_0_, student0_.name as name0_0_ from t_student student0_ where student0_.id=?
-小胡
Hibernate: select courses0_.student_id as student1_1_, courses0_.course_id as course2_1_, course1_.id as id2_0_, course1_.name as name2_0_ from t_signup courses0_ left outer join t_course course1_ on courses0_.course_id=course1_.id where courses0_.student_id=?
--《心理應激微反應》
--《哈利·波特與遺傳學》
細心的你應該早就發現了,每一個同學選修課程的成績呢?
上述方法並不適合給多對多的關系加入額外的屬性。那怎麽辦呢?能夠用兩個一對多關系來實現,即能夠手動將中間表設計成一個實體,並為其配置映射關系。所以通常情況下,一個多對多關系也能夠用兩個一對多關系來實現。
【 轉載請註明出處——胡玉洋《【SSH高速進階】——Hibernate 多對多映射》】
【SSH高速進階】——Hibernate 多對多映射