@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
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM