iT邦幫忙

2024 iThome 鐵人賽

DAY 12
0

https://ithelp.ithome.com.tw/upload/images/20240904/20150977s7zH4hK4Ja.png

一對多 1 : N

一對多關聯可以看到,products 和 reviews 這兩張表的關係,一個商品會有多則評論,所以設計上會在 reviews 裡面紀錄 product_id 來關聯回去 products。會應用到 @OneToMany @ManyToOne 這兩種註解來根據你是哪一方進行關聯。

建立父實體 reviews,標記 @ManyToOne

@Entity
@Data
@Table(name = "reviews")
@JsonIgnoreProperties({"product"})
public class Review {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String comment;
    private int rating;

    @ManyToOne
    @JoinColumn(name = "product_id", referencedColumnName = "id")
    private Product product;
}

注意 reviews 是多的那邊所以用 @ManyToOne ,和一對一配置相同,如果是父實體就會用上 @JoinColumn 並且標出 FK 的欄位。

建立子實體 products,標記 @OneToMany

@Entity
@Data
@Table(name = "products")
//@JsonIgnoreProperties({"productDetail"}) 
//@JsonIgnoreProperties({"reviews"}) 
public class Product {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;
    private Double price;
    private String description;

    @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @JoinColumn(name = "product_detail_id", referencedColumnName = "id")
    private ProductDetails productDetails;

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "product")
    private List<Review> reviews;
}

這邊也配置雙向關聯回去,但是要記得使用 @JsonIgnoreProperties 來指定某些屬性不要序列化成 Json 避免雙向循環,假設你是純粹要把關聯用再查 Review 時可以帶出關聯的 Product 就可以不用在 Product 的 Entity 寫 @OneToMany 的部分,但如果要從 Product 關聯回去 Review 就必須兩邊都綁定,因為 Product 在這邊屬於被子實體,要 mappedBy 確定父實體的關聯屬性,沒辦法單方向關聯回去。

這邊我們讓 Product 可以關聯回去 Review 所以可以查到下面這樣

[
    {
        "id": 1,
        "name": "最後生還者",
        "price": 59.99,
        "description": "由 Naughty Dog 開發的動作冒險遊戲。",
        "productDetails": {
            "id": 1,
            "developer": "Naughty Dog",
            "publisher": "Sony Interactive Entertainment",
            "releaseDate": "2013-06-14",
            "languageSupport": "English, Japanese, Chinese"
        },
        "reviews": [
            {
                "id": 1,
                "comment": "這是一款令人驚嘆的遊戲,擁有引人入勝的故事和令人驚嘆的視覺效果!",
                "rating": 5
            },
            {
                "id": 11,
                "comment": "遊戲不錯,但希望戰鬥系統能更具挑戰性。",
                "rating": 4
            },
            {
                "id": 12,
                "comment": "每一秒鐘都充滿樂趣,真的是一款精緻的遊戲!",
                "rating": 5
            }
        ]
    },
    {
        "id": 2,
        "name": "巫師3",
        "price": 49.99,
        "description": "由 CD Projekt Red 開發的開放世界角色扮演遊戲。",
        "productDetails": {
            "id": 2,
            "developer": "CD Projekt Red",
            "publisher": "CD Projekt",
            "releaseDate": "2015-05-19",
            "languageSupport": "English, Chinese, Polish"
        },
        "reviews": [
            {
                "id": 2,
                "comment": "很棒的遊戲,但某些部分的節奏感覺有點慢。",
                "rating": 4
            },
            {
                "id": 13,
                "comment": "畫質很好,但劇情有點單調。",
                "rating": 3
            }
        ]
    },
    // ......略
]

關於一對多的設置上其實跟一對一很類似,主要都是要區別出哪個是父實體和子實體,一開始規劃資料表時就可以根據此來配置關聯的欄位,實際撈取資料上也要根據需求決定是否需要雙向關聯,回傳的資料上也可以採用 DTO 的方式可以回傳需要的欄位,中間實作上也要避免雙向循環,這樣就可以好好應用這些關聯方式,下一篇來介紹多對多的部分。

Ref:


上一篇
Day 11 - Spring Data JPA (3)資料庫關聯 1 : 1
下一篇
Day 13 - Spring Data JPA (5)資料庫關聯 N:N
系列文
關於我和 Spring Boot 變成家人的那件事15
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言