@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练习小项目:学员管理系统设计开发 带着项目需求学习是最有趣和效 ...
随机推荐
- hustOJ 添加 golang 支持
hustOJ 支持Go1.7.1 是否为docker环境不重要,此处所有内容均为docker中执行,普通主机手动安装则更加如此 建议在docker中执行,因为OJ为严控恶意权限,judge_clien ...
- iptables和netfilter
1.iptables和netfilter说明 [1]netfilter/iptables组成Linux平台下的包过滤防火墙,iptables是用户空间的管理工具,netfilter是内核空间的包处理框 ...
- MacBook Home End
For the Home command, press down the Fn + Left Arrow keystroke combination. For the End command, pre ...
- java异常处理——finally相关
示例程序1 public class EmbededFinally { public static void main(String args[]) { int result; try { Syste ...
- springboot+VUE(二)
入element-ui cnpm install element-ui -S 执行后,会下载element-ui的包到本地,同时会将配置加入到package.json的依赖块中. 通过命令行可以将最新 ...
- caffe学习笔记1
博客 http://blog.csdn.net/seven_first/article/details/47378697 https://zhuanlan.zhihu.com/p/25127756?r ...
- 佳鑫:信息流广告CTR一样高,哪条文案转化率更好?
在优化信息流广告的过程中,你有没有遇到这样的帐户? 投了几个AB方案,点击率好不容易上去了,但转化率还是有的高.有的低! 这儿就有这么一个为难的案例: 一个广告主计划向有意愿在北京预订酒店的用户投放信 ...
- arcgis10.2 sde配置
本机配置好oracle11g server 64位+client 32位.
- Tesseract-OCR的使用记录
参考: http://www.cnblogs.com/cnlian/p/5765871.html http://www.cnblogs.com/wzben/p/5930538.html 1.下载 Te ...
- Programming Series 1.0 — C Programming
In the growing world of technology, C programming has kind of lost its way. Today, we have a million ...