程式開發中,不同實體之間的關係就像多角戀,有多對多、一對多等各種複雜關係,但其實只要梳理清楚,就能使結構更加清晰。在物件關係映射(ORM)中,正確處理實體關係是非常重要的,特別是使用JPA(Java Persistence API),掌握不同的實體關係及配置,能夠有效操控資料庫。
實體關係主要分為三種:
意指每個實體都只有一個對應的實體。例如,member對應唯一的address,代表每一member只會有一個address,反之亦然。
使用@OneToOne註解定義此一關係:
@Entity
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "address_id", referencedColumnName = "id")
private Address address;
}
@Entity
public class Address {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String street;
private String city;
}
cascade是指定對實體操作時,另一方實體是否會級聯影響:
表示一個實體擁有多個實體,這些實體屬於同一個實體。例如一個專案底下有多個任務,而這些多個任務共同屬於同一個專案。
使用@OneToMany或@ManyToOne註解定義此一關係:
@Entity
public class Project {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToMany(mappedBy = "project", cascade = CascadeType.ALL)
private List<Task> tasks = new ArrayList<>();
}
@Entity
public class Task {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne
@JoinColumn(name = "project_id")
private Project project;
}
mappedBy是指定在雙向關聯當中,關係的擁有方是誰。
以上例而言,Task實體當中的project是擁有方,因此Project類要使用 mappedBy = "project",這樣讓JPA知道兩者關聯,避免產生多餘的中間表。
每個實體都可以與多個實體產生關聯,例如tag跟project,每個project可以有多個tag,而每個tag也可以對應多個project。在JPA當中,實現多對多關係,通常需要一個中間關聯表實現。
使用@ManyToMany註解定義此一關係:
@Entity
public class Project {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToMany
@JoinTable(
name = "project_tag",
joinColumns = @JoinColumn(name = "project_id"),
inverseJoinColumns = @JoinColumn(name = "tag_id")
)
private Set<Tag> tages = new HashSet<>();
}
@Entity
public class Tag {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToMany(mappedBy = "tages")
private Set<Project> projectes = new HashSet<>();
}
JAP會自動創建project_tag中間表,透過註解產生中間表管理他們之間多對多關係。不用手動處理關聯表。
綜合上述,了解實體的關係是非常重要,能夠維持資料完整性以及擴展性,使用JAP的配置能有效操作資料庫,避免多餘表格產生,使程式運行順利。