专栏首页Danny的专栏【SSH快速进阶】——Hibernate 多对多映射

【SSH快速进阶】——Hibernate 多对多映射

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/huyuyang6688/article/details/50394226

  说到多对多关系,印象最深刻的就是大学的选修课。一个学生可以选修多门课程,一门课程可以有多个学生选修,学生所选的每一门课程还有成绩。这个场景的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 多对多映射》】

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 【MyBatis框架点滴】——MyBatis一对多查询

    版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/huyuyang6688/article/...

    DannyHoo
  • 【SSH快速进阶】——Hibernate一对一映射(one-to-one)——唯一外键关联

    版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/huyuyang6688/article/...

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

    版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/huyuyang6688/article/...

    DannyHoo
  • Mybatid关联表查询

    一、一对一关联  1.1、提出需求   根据班级id查询班级信息(带老师的信息) 1.2、创建表和数据   创建一张教师表和班级表,这里我们假设一个老师只负...

    汤高
  • MyBatis 实现关联表查询

    一、一对一关联  1.1、提出需求   根据班级id查询班级信息(带老师的信息) 1.2、创建表和数据   创建一张教师表和班级表,这里我们假设一个老师只负责教...

    庞小明
  • MyBatis学习总结(五)——实现关联表查询

    一枝花算不算浪漫
  • SQL学习笔记三(补充-3)之MySQL完整性约束

    是否可空,null表示空,非字符串 not null - 不可空 null - 可空

    Jetpropelledsnake21
  • “房间里有100个人,每人都有100元钱,每轮每人要拿一元钱随机给另一个人”最后分布的python结果

    下午看到了这个问题,一开始直觉当然是觉得每个人的期望都是一样的,大家都是公平的,最后肯定是差不多。

    钱塘小甲子
  • 「数据库」sql刷题(No.6)

    Hello 各位 ,我是公号「八点半技术站」的创作者 - Bruce.D (姓氏:豆)。

    八点半的Bruce、D
  • pt-osc在线重建表导致死锁的分析及对应的优化方案

    在业务低峰通过pt-osc在线做DDL期间出现死锁,导致业务的SQL被回滚了,对应用不友好。 本案例死锁发生的场景:pt-osc拷贝最后一个chunk-siz...

    老叶茶馆

扫码关注云+社区

领取腾讯云代金券