新建了一个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的学习的更多相关文章

  1. 码农小汪-Hibernate学习8-hibernate关联关系注解表示@OneToMany mappedBy @ManyToMany @JoinTable

    近期我也是有点郁闷,究竟是程序中处理关联关系.还是直接使用外键处理关联关系呢?这个的说法不一致!程序中处理这样的关联关系的话.自己去维护这样的约束.这样的非常乐观的一种做法!或者是直接在数据库中处理这 ...

  2. 【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 ...

  3. 《Django By Example》第二章 中文 翻译 (个人学习,渣翻)

    书籍出处:https://www.packtpub.com/web-development/django-example 原作者:Antonio Melé (译者注:翻译完第一章后,发现翻译第二章的速 ...

  4. EF Code First学习系列

    EF Model First在实际工作中基本用不到,前段时间学了一下,大概的了解一下.现在开始学习Code First这种方式.这也是在实际工作中用到最多的方式. 下面先给出一些目录: 1.什么是Co ...

  5. EF(Entity Framework)系统学习系列

    好久没写博客了,继续开启霸屏模式,好了,废话不多说,这次准备重新系统学一下EF,一个偶然的机会找到了一个学习EF的网站(http://www.entityframeworktutorial.net/) ...

  6. SSH学习笔记

    Struts2登录模块处理流程: 浏览器发送请求http://localhost/appname/login.action,到web应用服务器: 容器接收到该请求,根据web.xml的配置,服务器将请 ...

  7. 11.Configure Many-to-Many(配置多对多关系)【Code-First系列】

    现在学习EF Code-First多对多的配置. 这里我们举例:学生和班级实体,一个学生可以选修多个课程,多个学生也可以选修同一个课程. 一.使用数据注解特性,配置多对多的关系 using Syste ...

  8. Hibernate学习笔记(二)

    2016/4/22 23:19:44 Hibernate学习笔记(二) 1.1 Hibernate的持久化类状态 1.1.1 Hibernate的持久化类状态 持久化:就是一个实体类与数据库表建立了映 ...

  9. Python学习路程day18

    Python之路,Day18 - Django适当进阶篇 本节内容 学员管理系统练习 Django ORM操作进阶 用户认证 Django练习小项目:学员管理系统设计开发 带着项目需求学习是最有趣和效 ...

随机推荐

  1. (整理) .NET IIS性能优化

    本文收集了部分性能优化的方式,缓存.压缩.线程池调整等等,仅供参考. 1 .NET 程序中的调整 程序Sqlhelper中使用缓存 使用JSON序列化器(Jil)取代Json.NET 2 .NET 程 ...

  2. tornado+jsonrpc

    rpc:远程过程调用(A服务调用B服务的一个方法或函数) tornado中jsonrpc的使用 import json import tornado.httpserver import tornado ...

  3. 【HDFS API编程】图解客户端从HDFS读数据的流程

  4. matlab-双摆仿真

    在物理学和数学中,在动力系统领域,双摆是一个摆锤,另一个摆锤连接在其末端,是一个简单的物理系统,具有丰富的动态特性,对初始条件具有很强的敏感性.双摆的运动由一组耦合的常微分方程控制并且是混沌的. 由于 ...

  5. python大法好——飞机大战完整吧

    # -*- coding:utf-8 -*-import pygamefrom pygame.locals import *import time '''说明1.按下b键,让玩家飞机爆炸 2.爆炸效果 ...

  6. leetcode978

    class Solution(object): def maxTurbulenceSize(self, A: 'List[int]') -> int: n = len(A) if n == 1: ...

  7. MATLAB 出一张好看的图

    1.坐标轴的视点(viewpoint):从哪个方向看整个坐标系统,这决定了坐标轴的方向和位置,通过view函数实现视点的设置:view([z y ]):(将坐标系统想象为一座房子,而自己是个会飞的天使 ...

  8. Ajax需要带头信息跨域问题的解决

    $.ajax({ type:"get", url:"http://localhost:8082/index/getMsg", dataType:'json', ...

  9. 警惕 MySql 更新 sql 的 WHERE 从句中的 IN() 子查询时出现的性能陷阱

    警惕 MySql 更新 sql 的 WHERE 从句中的 IN() 子查询时出现的性能陷阱 以下文章来源:https://blog.csdn.net/defonds/article/details/4 ...

  10. H5自定义金额键盘,改良后ios体验效果流畅

    下载的别人的插件改良一下,源码地址:https://github.com/XieTongXue/how-to/tree/master/pay-h5 没有插件,直接来代码 <div class=& ...