一个学生可以选多门课

一门课程有多个学生上

实现步骤:

一、学生

(1)数据库创建学生数据表students,包含id,name字段

设置id字段为主键,类型:bigint,自增

设置name字段,类型:nvarchar(50)

(2)创建Student.java实体类,对应数据表

package com.zit.entities;

import java.util.HashSet;
import java.util.Set; import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.Id; public class Student { private long id; private String name; private Set<Course> courses = new HashSet<Course>(); public Student(){ } public long getId() {
return id;
} public void setId(long id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public Set<Course> getCourses() {
return courses;
} public void setCourses(Set<Course> courses) {
this.courses = courses;
} }

  

(3)创建映射文件Student.hbm.xml,表明映射关系

1、Student.hbm.xml

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping>
<class name="com.zit.entities.Student" table="students">
<id name="id" column="id" type="long" >
<generator class="native"/>
</id>
<property name="name" column="name" type="string"/>
<!-- 添加中间表映射 -->
<set name="courses" table="students_courses" cascade="save-update" inverse="false">
<key column="student_id"></key>
<many-to-many class="com.zit.entities.Course" column="course_id"></many-to-many>
</set>
</class>
</hibernate-mapping>
()<class>的name:实体类路径, table:数据表名字

()id的<generator class="native"/>:主键生成策略,因为我在数据表已让主键id字段自增,这里设置native(别的百度一下即可)

()id的column:对应数据表字段id,数据表为bigint类型,对应Java的long类

()<set>标签:设置中间表

  table:中间表表名,

  cascade:什么情况下进行关联操作,这里设为save-update,所以save时会进行关联操作

  inverse:true/false,由false的一方维护,这里是多对多,双方维护,双方都为false

  <key column>:对应中间表的字段student_id,指定为students表的id的外键

  <many-to-many>:class:它指出与Student类进行关联的类,即Course; column:指定为courses表的主键id的外键


Course.hbm.xml中与之相反即可,具体见下面具体配置

二、课程

(1)数据库创建课程数据表courses,包含id,name字段(与学生表相同即可)

设置id字段为主键,类型:bigint,自增

设置name字段,类型:nvarchar(50)

(2)创建Course.java实体类,对应数据表

package com.zit.entities;

import java.util.HashSet;
import java.util.Set; public class Course { private long id; private String name; private Set<Student> students = new HashSet<Student>(); public Course(){ } public long getId() {
return id;
} public void setId(long id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public Set<Student> getStudents() {
return students;
} public void setStudents(Set<Student> students) {
this.students = students;
} }

  

(3)创建映射文件Course.hbm.xml,表明映射关系

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping>
<class name="com.zit.entities.Course" table="courses">
<id name="id" column="id" type="long" >
<generator class="native"/>
</id>
<property name="name" column="name" type="string"/>
<!-- 添加中间表映射 -->
<set name="students" table="students_courses" cascade="save-update" inverse="false">
<key column="course_id"></key>
<many-to-many class="com.zit.entities.Student" column="student_id"></many-to-many>
</set>
</class>
</hibernate-mapping>

  

三、中间表

由Hibernate自动生成中间表,不需自己创建

它是根据Student.hbm.xml和Course.hbm.xml中的映射自动生成对应字段,

student_id字段,是students表的主键id的外键

course_id字段,是courses表的主键id的外键

如下图所示:

四、 测试代码:

(运行后自动生成中间表)

1、一个学生,选了两门课——“语文”、“化学”

2、一门课程,有两个学生——“杨洋1”、“杨洋2”

	@Resource(name = "sessionFactory")
private SessionFactory sessionFactory; @Override
@Transactional
public void insert() {
//getCurrentSession()比openSession()安全,注意web.xml中的配置,不然会报错
Session session = sessionFactory.getCurrentSession();
Transaction tran = session.beginTransaction(); // 1、王晓东1选了两门课
Student s1 = new Student();
s1.setName("王晓东1"); Course c1 = new Course();
c1.setName("语文");
Course c2 = new Course();
c2.setName("化学"); s1.getCourses().add(c1);
s1.getCourses().add(c2); session.save(s1); // 2、英语课有两个学生
// Course c3 = new Course();
// c3.setName("英语");
// Student s2 = new Student();
// s2.setName("杨洋1");
// Student s3 = new Student();
// s3.setName("杨洋2");
// c3.getStudents().add(s2);
// c3.getStudents().add(s3);
// session.save(c3); tran.commit();
session.flush();//
session.close();
}

  注意commit后,要flush刷到数据库

我的SessionFactory使用了SSH框架的注解配置 (根据自己的方式来获得Session即可)

SSH框架搭建完整实例参考我的另一篇博客:  http://www.cnblogs.com/Donnnnnn/p/7481357.html

实现效果:

1、一个学生,选了两门课——“语文”、“化学”

(1)控制台显示执行的sql语句

Hibernate: insert into students (name) values (?)
Hibernate: insert into courses (name) values (?)
Hibernate: insert into courses (name) values (?)
Hibernate: insert into students_courses (student_id, course_id) values (?, ?)
Hibernate: insert into students_courses (student_id, course_id) values (?, ?)

可以看到,往学生表、课程表和中间表都插入了数据

(2)数据库

students表:

courses表:

students_courses表:

2、一门课程,有两个学生——“杨洋1”、“杨洋2”

同上

参考别人博客:

https://www.cnblogs.com/whgk/p/6121593.html

Hibernate多对多映射(双向关联)实例详解——真的更多相关文章

  1. hibernate一对一外键双向关联

    关联是类(类的实例)之间的关系,表示有意义和值得关注的连接. 本系列将介绍Hibernate中主要的几种关联映射 Hibernate一对一主键单向关联Hibernate一对一主键双向关联Hiberna ...

  2. hibernate一对一主键双向关联

    关联是类(类的实例)之间的关系,表示有意义和值得关注的连接. 本系列将介绍Hibernate中主要的几种关联映射 Hibernate一对一主键单向关联Hibernate一对一主键双向关联Hiberna ...

  3. hibernate集合映射inverse和cascade详解

    hibernate集合映射inverse和cascade详解   1.到底在哪用cascade="..."? cascade属性并不是多对多关系一定要用的,有了它只是让我们在插入或 ...

  4. 一对一关联查询注解@OneToOne的实例详解

    表的关联查询比较复杂,应用的场景很多,本文根据自己的经验解释@OneToOne注解中的属性在项目中的应用.本打算一篇博客把增删改查写在一起,但是在改的时候遇到了一些问题,感觉挺有意思,所以写下第二篇专 ...

  5. Entity Framework实例详解

    Entity Framework Code First的默认行为是使用一系列约定将POCO类映射到表.然而,有时候,不能也不想遵循这些约定,那就需要重写它们.重写默认约定有两种方式:Data Anno ...

  6. 【eclipse插件开发实战】 Eclipse插件开发5——时间插件Timer开发实例详解

    Eclipse插件开发5--时间插件Timer开发实例详解 这里做的TimeHelper插件设定为在菜单栏.工具栏提供快捷方式,需要在相应地方设置扩展点,最后弹出窗体显示时间. 在上一篇文章里创建好了 ...

  7. C#操作SQLite方法实例详解

    用 C# 访问 SQLite 入门(1) CC++C#SQLiteFirefox  用 C# 访问 SQLite 入门 (1) SQLite 在 VS C# 环境下的开发,网上已经有很多教程.我也是从 ...

  8. 官网实例详解-目录和实例简介-keras学习笔记四

    官网实例详解-目录和实例简介-keras学习笔记四 2018-06-11 10:36:18 wyx100 阅读数 4193更多 分类专栏: 人工智能 python 深度学习 keras   版权声明: ...

  9. 实例详解 Java 死锁与破解死锁

    锁和被保护资源之间的关系 我们把一段需要互斥执行的代码称为临界区.线程在进入临界区之前,首先尝试加锁 lock(),如果成功,则进入临界区,此时我们称这个线程持有锁:否则呢就等待,直到持有锁的线程解锁 ...

随机推荐

  1. C#接口实现技巧之借助第三方

    一个类继承了一个接口,对接口实现通常的做法---直接在这个类中对接口进行实现. 利用继承的概念,可以很巧妙地借助第三方类对接口进行实现,这种方式在实际的项目开发过程中其实用途很是比较大的,至少我们的游 ...

  2. windows安装使用docker

    doker就是一个容器,如果想要在windows安装还必须要用另外一个工具docker-toolbox.下载地址:https://mirrors.aliyun.com/docker-toolbox/w ...

  3. ggplot2画图

    早在N年前就听说这个包画图不错,一直没机会用,终于等到了.相比前面trendline这个包的可视化功能强大得多. ggplot2需要使用dataframe,其实就是一个N维数组, install.pa ...

  4. 基于 Spring Cloud 完整的微服务架构实战

    本项目是一个基于 Spring Boot.Spring Cloud.Spring Oauth2 和 Spring Cloud Netflix 等框架构建的微服务项目. @作者:Sheldon地址:ht ...

  5. Getting started with Processing 第十三章——延伸(2)

    与 Arduino 联动 在 Processing 中,可以通过:import processing.serial.* Serial port; //声明串口对象port = new Serial(t ...

  6. javascript之封装(引用网络)

    一. 例:事件监听封装 jQuery 中的事件监听,完全可以用 addEventListener/attachEvent 模拟,分别对应于现代浏览器和 IE ,可以把两个方法封装一下,但是为了方便,这 ...

  7. 框架设计——View

    [demo]: ZZSZYFP : UserControl, INavigateMdiControl(1)继承自UserControl,并实现了 INavigateMdiControl接口(2)限制表 ...

  8. 关于Mysql 查询所有表的实时记录用于对比2个MySQL 库的数据是否异步

    Xu言: 今天,为了研究一个MySQL主从同步开机后报错 问题,如下图 故障原因分析: 经过分析,可能是主从服务器开机顺序导致.(有待下次断电再次测试) 主从错误提示:日志读取错误的问题.解决方法:更 ...

  9. 手机中SN、MEID、IMEI的意思

    SN SN码是Serial Number的缩写,有时也叫SerialNo,也就是产品序列号,产品序列是为了验证“产品的合法身份”而引入的一个概念,它是用来保障用户的正版权益,享受合法服务的:一套正版的 ...

  10. python的索引问题

    之前自己在python索引中一直遇到这样的问题: data = np.arange(12).reshape((3,4)) print(data[:][0]) 想要索引第一列时总是索引到第一行,后来发现 ...