iT邦幫忙

2023 iThome 鐵人賽

DAY 17
0
自我挑戰組

Spring Boot 三十天挑戰賽系列 第 17

Day 17 - From One-to-One to Many-to-One

  • 分享至 

  • xImage
  •  

鐵人賽一乍眼過半啦!

Yes

隨著資料庫技術的發展,Entity 間的關聯在資料模型中佔有重要的位置。在開發時,我們經常遇到如何模擬現實世界中各種複雜的關係。在

今天來談談 Spring Data JPA 中最常用的兩種關聯:One-to-One 和 Many-to-One。

一、One-to-One 關聯

如字面上所述,就是一個實體與另一個實體間有著一對一的關聯。

範例:
假設我們要開發一個員工資料系統。每位員工都有一張員工證。在這裡,員工和員工證間就形成了一個 One-to-One 的關聯。

@Entity
public class Employee {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @OneToOne(mappedBy = "employee", cascade = CascadeType.ALL)
    private WorkCard workCard;
}

@Entity
public class WorkCard {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @OneToOne
    @JoinColumn(name = "employee_id")
    private Employee employee;
}

我們透過 @OneToOne 註解建立了 EmployeeWorkCard 之間的一對一關聯。

二、Many-to-One 關聯

Many-to-One 的概念則是多個 Entity 可以對應到同一個 Entity。
假設我們還是在開發員工資料系統,這次要添加部門概念。一個部門可以有多位員工,但每位員工只隸屬於一個部門。這邊員工和部門間就形成了一個 Many-to-One 的關聯。

@Entity
public class Department {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @OneToMany(mappedBy = "department")
    private List<Employee> employees;
}

@Entity
public class Employee {
    // ... 其他屬性

    @ManyToOne
    @JoinColumn(name = "department_id")
    private Department department;
}

利用 @ManyToOne 註解表示每位員工只屬於一個部門。而部門則用 @OneToMany 表示一個部門可以有多位員工。

三、One-to-One 挑戰

  1. 雙向關聯中的「主控方」問題

    在雙向關聯中,我們需要確定哪一邊是主控方 (owning side),錯誤設定主控方會導致資料不一致。

    一般來說,我們會將具有 FK 的那一邊設為主控方。在上述的例子中,WorkCard 包含一個指向 Employee 的外鍵,所以它是主控方。


四、Many-to-One 挑戰

  1. N+1 查詢問題

    從部門中取得員工時,可能會遇到 N+1 查詢問題。如果我們有 N 個部門,可能會發出 N+1 次的查詢。

    → 使用 JPA 的 JOIN FETCH 或 Hibernate 的 BatchSize 註解可以有效解決這個問題。

  2. 延遲加載與即時加載

    在 JPA 中,我們可以選擇使用延遲加載 (LAZY) 或即時加載 (EAGER)。選擇不當可能導致效能問題或 LazyInitializationException

    → 對於大多數的關聯,使用延遲加載是比較好的選擇。只有當確定每次都需要使用關聯資料時,才考慮使用即時加載。


五、Best Practice

  1. 盡量避免使用雙向關聯:雖然雙向關聯提供了更大的靈活性,但它也帶來了許多問題。如果可以,優先考慮使用單向關聯。
  2. 使用對應的關聯註解:例如,不要在一對多的關聯中使用 @OneToOne 註解。
  3. 減少 Eager 加載:如非必要,避免使用 FetchType.EAGER,因為它可能導致效能問題。

透過今天的文章,可以大致了解 One-to-One 和 Many-to-One 這兩種關聯的基礎使用方法。在實際開發中,當然還有很多細節和問題(坑 XD)等著我們解決,在接下來的兩天中會繼續探討其他關聯方式~


上一篇
Day 16 - Spring Data JPA Entity Relation
下一篇
Day 18:One-to-Many
系列文
Spring Boot 三十天挑戰賽30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言