@ManyToMany的学习
新建了一个manyToMany的学生-课程表,学生可以选择多个课程,多个课程可以被学生选。尝试如下代码,创建了两个list,然后新建对象,加入list,然后set《list》,报错,这是因为new的新对象
都是暂时的,米有加入。但在这样会生成一个中间表,虽然此时保存了course,中间表需要student,而student是暂时对象,所以报错。
数据库如图:


student中啥也没有。因为没有保存,是暂时对象
错误代码:
student: @ManyToMany
private List<Course> courses;
--------------------------------------
course:
@ManyToMany
private List<Student> students;
----------------------------------
测试代码:
List<Course> courses=new ArrayList<>();
List<Student> students=new ArrayList<>();
------------------------------------------
Student student01=new Student();
student01.setStudentName("student01");
students.add(student01);
Course course01=new Course();
course01.setCourseName("Course01");
courses.add(course01);
student01.setCourses(courses);
course01.setStudents(students);
this.courseDao.save(course01);
this.studentDao.save(student01);
------------------------------------------------------------------------------------------------------------------------------------------------------- 这时候我加入了两个1.mappedBy,用在被维护端,这里的course作为被维护端,student作为维护端,这里只要加了mappedBy的那一端,就意味着放弃了对关系的维护,也不能增删改查中间表的关系。
inverse是控制反转,加了就意味着放弃维护关系的权力。下面是我创建成功的表的截图
在这里用jointable,测试还是上面的方法,没有动,然后就student和course都成功了
这时候你也可以指定在jointable中name指定表名,然后指定外键,joinColumns是主操作表的中间表列,可以有好几个,而inverseJoinColumns是副操作表的中间表列,也就是student作为主操作表,
然后course作为子操作表,我尝试改过@JoinColumn(name="student_ID")变成@JoinColumn(name="student_ID~"),然后中间表就生不成了。 下面是生成上表的代码
course:
@ManyToMany(cascade = CascadeType.REMOVE,fetch = FetchType.EAGER,mappedBy="courses")
private List<Student> students;
student:
@ManyToMany(fetch = FetchType.EAGER,cascade = CascadeType.REMOVE)
@JoinTable(name="students_course"//指定中间的名字是students_course,如果不写也会默认生成,格式是主控方+被控方,或者是joinTable在哪里,就是谁在前
//joinColumns={@JoinColumn(name="student_ID")},//这个是用来指定中间表的主键的,如果不指定,默认为双方表的主键
//inverseJoinColumns={@JoinColumn(name="course_ID")}//这个是用来指定中间表的放弃控制的表的,inverse嘛,就是控制反转,放弃控制权限。因为这里已经用了mappedBy,已经放弃了
)
下面的代码是用来测试被放弃的一端能不能操纵数据库的片段代码,发现并不能删除中间表的关系
test:
Course course01=this.courseDao.findByCourse_name("Course01");
List<Student> students=course01.getStudents();
for (int i=0;i<students.size();i++){
if (students.get(i).getStudentName().equals("student02")){
students.remove(students.get(i));
course01.setStudents(students);
this.courseDao.save(course01);
System.out.println("删除关系成功");
}else {
System.out.println("不存在关系");
}
}
上面是指定了student作为主控方的,我们来测试一下,下面是测试代码和测试结果,中间表中的一个关系被删除了
操作方法是,先找到这个学生,然后得到他的选课list,然后move掉list中的某个,再进行保存
Student student01=this.studentDao.findByStudent_name("student01");
List<Course> courses=student01.getCourses();
for (int i=0;i<courses.size();i++){
if(courses.get(i).getCourseName().equals("course02")){
courses.remove(courses.get(i));
student01.setCourses(courses);
this.studentDao.save(student01);
System.out.println("删除关系成功");
}else {
System.out.println("不存在关系");
}
}

-----------------------------
student:
@ManyToMany()
@JoinTable()//创建了中间表
private List<Course> courses;
-----------------------------
course:
@ManyToMany(mappedBy = "courses")//被维护端
--------------------------------------------------------------------------------------------------------------------------------------------------------
在之后我在测试中,注释了student的保存的save方法,留着course的save,于是可以运行成功,course保存,然后student还是空表,当然student-cours也是空表,数据库的默认中间表是这样的,
谁作为维护,谁在前,比如这里的中间表是student。
this.courseDao.save(course01);
this.courseDao.save(course02);
// this.studentDao.save(student01);
// this.studentDao.save(student02);
-------------------------------------------------------------------------------------------------------------------------------------------------------
然后就是增删改查的操作了,findByStudent_name是我自己写的一个@Query函数,可以用id查。emm~写个删吧,
这是删中间表的关系,注意这里要设置成@ManyToMany(fetch = FetchType.EAGER),不然会爆出
session错误。因为这个已经跨表了 1.这个是删除对象,
2.删除被控方course:因为我上面设计的时候设计了级联,student和course都设置了REMOVE。额,,,我也不知我为什么设置,你删我,我删你,按照下面的代码做下去的时候,就全部删除了。course和student,
中间表都删除空了...
Course course01=this.courseDao.findByCourse_name("Course01");
this.courseDao.delete(course01);
System.out.println("删除course01成功");
3.在我把级联去掉后,我试着删除了student01,发现student中的student01被删除,然后中间表中的关系被删除,
// Student studen01=this.studentDao.findByStudent_name("student01");
// this.studentDao.delete(studen01);
// System.out.println("删除student01成功");
4.我在尝试一下删除course,发现可以删除成功,但是中间表没有进行更新修改,这就出问题了,课都没了,学生还在选,那可不行
Course course01=this.courseDao.findByCourse_name("Course01");
this.courseDao.delete(course01);
System.out.println("删除course01成功");
--------------------------------
// Course course01=this.courseDao.findByCourse_name("Course01");//这段代码是错误的,因为course已经设置为被维护端,不会维护,所以在操纵数据库的时候就只会
//进行查询,而不能进行修改。
// List<Student> students=course01.getStudents();
// for (int i=0;i<students.size();i++){
// if (students.get(i).getStudentName().equals("student02")){
// students.remove(students.get(i));
// course01.setStudents(students);
// this.courseDao.save(course01);
// System.out.println("删除关系成功");
// }else {
// System.out.println("不存在关系");
// }
// }
Student student01=this.studentDao.findByStudent_name("student01");//这段代码是正确的,因为students是维护方,如果进行删除操作,就会出现查询,删除操作,和保存。
List<Course> courses=student01.getCourses();
for (int i=0;i<courses.size();i++){
if(courses.get(i).getCourseName().equals("Course01")){
courses.remove(courses.get(i));
student01.setCourses(courses);
this.studentDao.save(student01);
System.out.println("删除关系成功");
}else {
System.out.println("不存在关系");
}
}
-------------------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------------------------
多对多的关系是靠第三表来维护的,所以不建议执行级联删除操作,可以直接修改第三表实现,比如student和course,
如果出现学生不选这门课程了,或者学生修改了其他的,是对中间表的操作,比如这里有俩学生,俩课程。如果是全选,也就是
2*2=4,中间表中有四条记录,那么修改的时候就只需要增删改查中间表就可以修改学生对应的选课。下面有个增的例子
增------------------------
List<Student> students=new ArrayList<>();
Student student01=new Student();
student01.setStudentName("student01");
students.add(student01);
Course course01=this.courseDao.findByCourse_name("Course01");
List<Course> courses=new ArrayList<>();
courses.add(course01);
course01.setStudents(students);
student01.setCourses(courses);
this.courseDao.save(course01);
this.studentDao.save(student01);
System.out.println("HHHHHHHHHH新建成功");
-------------------------------------------------------------------------------------------------------------------------------------------------------
如果不喜欢这个,可以进行级联保存,
放弃外键维护权:比如student和course,如果course放弃外键维护权,即不维护外键,也就是如果设置了student上设置级联保存,那么在新建student并且new了course放置在student里,进行
这时候保存student,student和course都会被保存,但这时course里的外键会是空。
(来源)https://blog.csdn.net/jjizh/article/details/76449334
-------------------------------------------------------------------------------------------------------------------------------------------------------
@JoinTable参数详解:
(来源)https://blog.csdn.net/jiangyu1013/article/details/79503581
@ManyToMany的学习的更多相关文章
- 码农小汪-Hibernate学习8-hibernate关联关系注解表示@OneToMany mappedBy @ManyToMany @JoinTable
近期我也是有点郁闷,究竟是程序中处理关联关系.还是直接使用外键处理关联关系呢?这个的说法不一致!程序中处理这样的关联关系的话.自己去维护这样的约束.这样的非常乐观的一种做法!或者是直接在数据库中处理这 ...
- 【Python学习笔记】Coursera课程《Using Databases with Python》 密歇根大学 Charles Severance——Week4 Many-to-Many Relationships in SQL课堂笔记
Coursera课程<Using Databases with Python> 密歇根大学 Week4 Many-to-Many Relationships in SQL 15.8 Man ...
- 《Django By Example》第二章 中文 翻译 (个人学习,渣翻)
书籍出处:https://www.packtpub.com/web-development/django-example 原作者:Antonio Melé (译者注:翻译完第一章后,发现翻译第二章的速 ...
- EF Code First学习系列
EF Model First在实际工作中基本用不到,前段时间学了一下,大概的了解一下.现在开始学习Code First这种方式.这也是在实际工作中用到最多的方式. 下面先给出一些目录: 1.什么是Co ...
- EF(Entity Framework)系统学习系列
好久没写博客了,继续开启霸屏模式,好了,废话不多说,这次准备重新系统学一下EF,一个偶然的机会找到了一个学习EF的网站(http://www.entityframeworktutorial.net/) ...
- SSH学习笔记
Struts2登录模块处理流程: 浏览器发送请求http://localhost/appname/login.action,到web应用服务器: 容器接收到该请求,根据web.xml的配置,服务器将请 ...
- 11.Configure Many-to-Many(配置多对多关系)【Code-First系列】
现在学习EF Code-First多对多的配置. 这里我们举例:学生和班级实体,一个学生可以选修多个课程,多个学生也可以选修同一个课程. 一.使用数据注解特性,配置多对多的关系 using Syste ...
- Hibernate学习笔记(二)
2016/4/22 23:19:44 Hibernate学习笔记(二) 1.1 Hibernate的持久化类状态 1.1.1 Hibernate的持久化类状态 持久化:就是一个实体类与数据库表建立了映 ...
- Python学习路程day18
Python之路,Day18 - Django适当进阶篇 本节内容 学员管理系统练习 Django ORM操作进阶 用户认证 Django练习小项目:学员管理系统设计开发 带着项目需求学习是最有趣和效 ...
随机推荐
- Chrome 58.xxx,iisExpress 创建的SSL网站显示安全正式错误Error:net::ERR_CERT_COMMON_NAME_INVALID
https://www.reddit.com/r/sysadmin/comments/677hep/chrome_58_not_supporting_self_signed_certificates/ ...
- Chapter07 链表(下):如何轻松学出正确的链表代码?
技巧一:理解指针或引用的含义 技巧二:指针丢失和内存泄漏 技巧三:利用哨兵简化实现难度 技巧四:重点留意边界条件处理 如果链表未空时,代码是否能够正常运行 如果链表只包含一个节点时,代码能否正常运行 ...
- 让WebStrom支持SSH协议的子项目
让WebStrom支持SSH协议的子项目 在大项目中, 经常会遇到子项目(submodule)使用ssh的情形, 但是WebStrom不直接支持它. 下面以MAC为例,在PC中的处理类似. 打开ter ...
- spring boot aop 自定义注解 实现 日志检验 权限过滤
核心代码: package com.tran.demo.aspect; import java.lang.reflect.Method; import java.time.LocalDateTime; ...
- Hibernate的查询方式
Hibernate的查询的方式 OID检索 get或load方法进行的查询 对象导航检索 linkman.getCustomer(); HQL检索 用于接收hql语句进行查询,面向对象查询方式. 通过 ...
- SpringCloud系列九:SpringCloudConfig 基础配置(SpringCloudConfig 的基本概念、配置 SpringCloudConfig 服务端、抓取配置文件信息、客户端使用 SpringCloudConfig 进行配置、单仓库目录匹配、应用仓库自动选择、仓库匹配模式)
1.概念:SpringCloudConfig 基础配置 2.具体内容 通过名词就可以发现,SpringCloudConfig 核心作用一定就在于进行配置文件的管理上.也就是说为了更好的进行所有微服务的 ...
- binlog2sql实现MySQL误操作的恢复
对于MySQL数据库中的误操作删除数据的恢复问题,可以使用基于MySQL中binlog做到类似于闪回或者生成反向操作的SQL语句来实现,是MySQL中一个非常实用的功能.原理不难理解,基于MySQL的 ...
- linux 之用户管理
用户的家目录 普通用户:/home/用户名/,所有者和所属组都是此用户,权限是700 超级用户:/root/,所有者和所属组都是root用户,权限是550 用户邮箱目录 /var/spool/mail ...
- NTP时间服务
时间服务 NTP:Network Time Protocol 作用:用来给其他主机提供时间同步服务 NTP的配置文件 /etc/ntp.conf NTP相关的命令 date:显示/修改系统时间 hwc ...
- jquery遍历----end()方法
定义和用法 end() 方法结束当前链条中的最近的筛选操作,并将匹配元素集还原为之前的状态. 举个栗子: <body> <ul class="first"> ...




