Udemy Course Spring JPA 25

ManyToMany

ZONGRU Li
6 min readMay 17, 2019

以學生與課程為例

一個課程可以有很多個學生

一個學生可以有多個課程

但是我們不會在course表內加上student_id,因為一個課程是對應多個學生id

我們也不會在student表格內加上course_id,因為一個學生對應多個課程id

所以我們會需要一個JOIN TABLE:

將相關設定實際設進course.java與student.java

上面除了分別加入ManyToMany的courses與students的ArrayList外

也加入get ArrayList與add單一筆的Method

接著執行DemoApplication得

會有多兩個join table

但是我們其實只想要一個join table就好

所以必須指定其中一方為owning side relationship

意即我們只想在某一方看到另一方的id欄位

例如student表格內有passport_id

所以student是owning side relationship(相對於passport來說)

在ManyToMany的關系下其他哪一方是owning side relationship差異不大

目前想指定student是owning side relationship(相對course)

所以我們只在course加上mappedBy

再次執行DemoApplication見到

在owning side relationship可以自己主動加上join table的annotation

並定義相關欄位

重新執行會見到

在該join table會加上FK欄位

原本join table內的STUDENTS_ID變成STUDENT_ID(沒有S)

接著我們要想如果INSERT DATA進這個JOIN TABLE

假設要寫入如下資料

在data.sql加入對應的INSERT語法

重新執行DemoApplication.java得

試著把三個table放在一起顯示

執行以下SQL句:

SELECT * FROM STUDENT_COURSE ,STUDENT,COURSE
WHERE STUDENT_COURSE.STUDENT_ID=STUDENT.ID
AND STUDENT_COURSE.COURSE_ID=COURSE.ID

同樣地我們想從java去取出上述JOIN TABLE中的資料

在StudentRepositoryTest中加入新的測試Method-retrieveStudentAndCourse

在左邊加入中斷點

用deBug mode觀察

最後執行完取的Course資料

由上圖可以看到,Course資料是由join table →student_course來的

所以可以得到一個結論是:

ManyToMany的預設fetch模式為:LAZY

我們暫時改為EAGER來看看會是什麼效果

會見到一個個join語法同時取出student與course資料如下

為程式效果考量,我們恢復成預設模式就好

建立相關INSERT Method

在StudentRepository加入以下Method

並在DemoApplication呼叫該方法

執行後進到H2-Console觀察

進到http://localhost:8090/h2-console

可以見到JOIN TABLE確實有insert我們要的資料

接著用deBug mode觀察結果

在完成student物件建立時可以看到如下

同理course物件

在完成em.persist(student); student物件會被附與id值

同理course物件也是

最後完成整個Method後(一直F7)就會看到

在整組Method為單位的交易遞出後會有三段INSERT

INSERT建立的student物件

INSERT建立的course物件

INSERT最後的JOIN TABLE資料

這就是我們想要的INSERT的結果

接著改寫上面的Method,改得更好用一點

原Method加上HardCode字樣

DemoApplication改寫呼叫

執行一樣得到:

目前為止的專案"SpringJPA深入ManyToMany(0517)"

--

--

ZONGRU Li
ZONGRU Li

Written by ZONGRU Li

2022/11/17 開源部分個人筆記給LINE "Java程式語言討論區"社群,希望能對社群的技術學習做一點點貢獻.(掩面....記得退訂閱!

No responses yet