Spring Data JPA (3) 資料庫關聯 1 : 1
操作 Spring Data JPA 需要對於資料表之間的關聯與配置有一定的了解,可以幫助你在規劃資料庫及撈取資料上有很大的幫助。
後續文章會依序介紹常見的幾種關聯操作,若這邊設計一個情境開設一個電商平台,賣電玩的商品,會有一些表紀錄商品的一些資訊,我們可以藉此來探討資料表之間的關聯。主要有下面這幾張表:
- products 商品資訊,記錄名稱 (name)、價錢 (price)、描述 (description)等資訊
- product_details 商品細節,紀錄開發商 (developer)、發行商 (publisher)、發行日 (release_date)、支援語言 (language_support)等資訊
- reviews 評論,紀錄評論者 (reviewer_name)、內容 (comment)、分數 (rating)
- tags 標籤,遊戲類型及各式分類標註 (name)
- product_tags 商品及標籤的關聯表 (多對多需要)
關聯配置相關參數介紹
關聯時必須知道誰是父實體(或稱維護方,具有 FK 可以關聯被維護 PK),誰是子實體(被維護、被參考對象)
父實體(維護方) | 子實體(被維護方) | |
---|---|---|
關聯 | 具有 FK | 被關聯 PK 或其他 |
註解應用區別 | @JoinColumn() | 關聯註解加入參數 mappedBy |
Cascade
級聯配置參數,針對父實體的資料操作,子實體會有對應自動操作
- CascadeType.ALL:無論儲存、更新、刷新或移除,一併對被參考物件作出對應動作。
- CascadeType.PERSIST:父實體進行儲存 (repository 的 save) 操作,自動對被關聯子實體進行儲存操作
- CascadeType.MERGE:父實體進行更新操作時,自動對關聯的子實體執行更新操作。
- CascadeType.REFRESH:父實體進行刷新操作時,自動對關聯的子實體執行刷新操作。
- CascadeType.REMOVE:父實體進行刪除操作時,自動對關聯的子實體執行刪除操作。
Fetch
資料讀取配置參數,設定讀取的方式是立即或是特定條件才讀
- FetchType.EARGE:馬上加載子實體
- FetchType.LAZY:只有應用到子實體的屬性時才會被加載
各類關聯註解預設值參考
Relation | Default |
---|---|
@OneToOne | FetchType.EARGE |
@ManyToOne | FetchType.EARGE |
@OneToMany | FetchType.LAZY |
@ManyToMany | FetchType.LAZY |
一對一 1 : 1
一對一的關聯可以從 products 和 product_details 這兩張表之間的關聯看到,一個商品會對應一個詳細資料,要透過 JPA 會用到 @OneToOne
註解來進行關聯,這些關聯註解都有一些參數可以設置。在這邊的範例就是 products 是父實體,product_details 是子實體。
定義父實體 products
1 |
|
@JoinColumn 的 name 參數指的是要提供 FK 的欄位名稱,referencedColumnName 是指被關聯方的 關聯欄位(不寫預設是被關聯的主鍵 PK)
定義子實體 product_details
1 |
|
這邊需要注意如果需要雙向關聯,這邊也要在關聯要呈現的屬性上面加上 @OneToOne(mappedBy = “{父方映射關聯的欄位}”),這邊也就是指父實體放 @OneToOne 欄位的變數名 productDetails
另外補充如果雙向關聯開啟,就會出現無限循環關聯的問題,你可以想像會出現 product 關聯出 product_details 但裡面又關聯回 product 就會一直永無止境導致回傳資料混亂,有幾個方法可以解決:
- 改用 DTO 將需要關聯資料裝入回傳
- @JsonIgnore 放在被關聯欄位上面就可以忽略關聯
- @JsonIgnoreProperties(”{關聯欄位變數名}”) 放在實體 class 上面
實際撈回來的資料
1 | [ |
以上就是基本一對一的關聯操作,下篇會來介紹一對多 (1 : N) 的操作模式。
這邊想要補充一下推薦有使用 Intellij 的 database UI ,連接好資料庫之後,對資料庫點右鍵選 Diagrams > Show Diagram 他就可以將各欄位之間的關聯狀況畫出來,還可以匯出圖片,就可以不用自己畫 ER 圖了,真的太強大 !!