1. 程式人生 > >【SSH高速進階】——Hibernate 多對多映射

【SSH高速進階】——Hibernate 多對多映射

pen prop package 轉載 map tex test lec set



  說到多對多關系。印象最深刻的就是大學的選修課。一個學生能夠選修多門課程,一門課程能夠有多個學生選修,學生所選的每一門課程還有成績

這個場景的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 多對多映射