【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 多对多映射》

时间: 2024-11-05 13:33:10

【SSH高速进阶】——Hibernate 多对多映射的相关文章

图解、详解Hibernate多对一映射

步骤1:案例代码. 步骤2:案例图解分析. ------------------------------------------------------------------------步骤1:案例代码------------------------------------------------------------------------------------------------------------------- 我们讲解Hibernate多对一映射的时候,首先想到的就是经典的

SSH学习四 Hibernate多对一的关系 + 增删改查

多对一关系实现起来不难,只需要在"多"的一方声明外键,声明外键在类的映射文件实现. 下面以老师学生为例,老师是1,学生是多 有一个有趣的地方,在Student类里面,没有声明teacherid这个属性,但是只要在配置文件声明了外键,那么就算类里面没有外键,配置文件的property也没有teacherid 下面是几个关键文件: 1.Student类(包含Student的增删改查) package com.learn.po; import org.hibernate.Session; i

Hibernate多对多映射关系(5)

单向 n-n n-n 的关联必须使用连接表 与 1-n 映射类似,必须为 set 集合元素添加 key 子元素,指定 CATEGORIES_ITEMS 表中参照 CATEGORIES 表的外键为 CATEGORIY_ID. 与 1-n 关联映射不同的是,建立 n-n 关联时, 集合中的元素使用 many-to-many. many-to-many 子元素的 class 属性指定 items 集合中存放的是 Item 对象, column 属性指定 CATEGORIES_ITEMS 表中参照 IT

hibernate多对多映射文件的配置

user.hbm.xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate

Hibernate 多对多映射

package com.entity.manytomany; import java.util.List; import javax.persistence.Entity; import javax.persistence.JoinColumn; import javax.persistence.JoinTable; import javax.persistence.ManyToMany; import com.entity.BaseEntity; @Entity public class St

【SSH快速进阶】——Hibernate继承映射:每个具体类映射一张表

上篇文章说的是每个类映射一张表,不管是父类还是子类.与上篇文章不同的是,这里是每个"具体类"映射一张表,什么意思呢?就是让每个子类(具体的.有意义的类)映射一张表. 场景 与上篇文章场景一样,如下类图 上图中Pig类和Bird类继承Animal类,要让每个具体类映射一张表,就是只映射Pig和Bird,如下表所示: (表 1) 上面的表有个特点就是,t_pig和t_bird的主键永远都不会相同.因为表面上看起来这是两张表,但实际上存储的都是动物(同一类型),所以还可以看做是一张表. 配置

【SSH快速进阶】——Hibernate继承映射:每个类映射一张表

上文说了每棵继承树映射一张表,本文继续描述让每个类都映射一张表的配置. 场景 与上篇文章场景一样,如下类图 上图中Pig类和Bird类继承Animal类,要让每个类映射一张表,就是让着三个类都分别映射一张表,但同时这三张表也跟对应的三个类似的,有继承关系,如下表所示: (表 1) Pig和Bird的记录都表示一个动物,因此都会在Animal对应的表中存储,而它们各自的拓展属性则存储在各自对应的表中,主键与Animal对应记录的主键各自对应. 配置 PO对象 跟上篇文章一样,实体类没有任何变化.

【SSH快速进阶】——Hibernate继承映射:每棵继承树映射一张表

我们都知道,Hibernate最大的一个优点就是使开发更加"面向对象",类与类之间有继承关系,Hibernate中也对这种继承关系提供了映射的封装. Hibernate为继承映射提供了三种策略 1.每棵继承树使用一张表 2.每个子类使用一张表 3.每个具体类使用一张表 本文对第一种策略进行说明. 场景 如下类图 上图中Pig类和Bird类继承Animal类,每棵继承树对应一张表,即在同一棵继承树中,所有的类的对象信息(记录)共同存放到一张表中,要判断某条记录属于哪个对象,需要在表中添加

ORM进阶之Hibernate中关系映射

ORM进阶之 ORM简介 ORM进阶之Hibernate简介及框架搭 ORM进阶之Hibernate的三大对象 ORM进阶之Hibernate中对象的三大状态解析 ORM进阶之Hibernate中一对一的关系映射 映射可以说是在hibernate中非常重要的一个内容,通过映射可以让程序员不再思考复杂的sql语句,而是更加的专注于业务逻辑的实现.映射通过一个xml配置文件完成并且我们可以对他进行修改!下边我们来看一下如何完成映射的! 单表映射 每个实体对应一张表,跟其他的实体没有关联关系,这是最简