問題描述
在利用Spring boot data JPA進行表設計的時候,表對象之間經常存在各種映射關系,如何正確將理解的映射關系轉化為代碼中的映射關系是關鍵之處。
解決辦法
概念理解
舉例:在公司的權限管理中,存在公司表、部門表、員工表。
- 公司表和部門表的關系:
主控方:部門表
被控方:公司表 - 部門表和員工表的關系:
由於是多對多的關系,不存在誰是主控方或被控方,兩者處於平行關系。
- 公司表和部門表的關系:
一對多或多對一,用外鍵關聯,若未設置級聯刪除,則刪除被控方記錄的時候會有外鍵約束。
- 多對多,用中間表關聯,刪除中間表的記錄,不會各方的表造成影響。
- 在該四個注解中,都含有屬性可設置,以下舉例兩個屬性。
- fetch=FetchType.LAZY為默認的數據延遲加載,fetch=FetchType.EAGER為急加載。
- cascade={CascadeType.PERSIST,CascadeType.MERGE,
CascadeType.REFRESH,CascadeType.REMOVE}.
其中:
CascadeType.PERSIST級聯新增(又稱級聯保存);
CascadeType.MERGE:級聯合並(級聯更新);
CascadeType.REMOVE:級聯刪除;
CascadeType.REFRESH:級聯刷新
CascadeType.ALL:以上四種都是;
一般采用CascadeType.MERGE:級聯合並(級聯更新)即可。默認值是均不進行關聯。
@OneToOne
- 在一對一的關系中,只需在主控方(數據總表)內注明@OneToOne,而被控方(員工表)只是作為外鍵,不需任何特殊標記。
@Entity
@Table(name = "costume_all_id")
public class AllId extends AbstractEntity {
private static final long serialVersionUID = 1L;
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "costume_member_fk")
private Member member;// 用戶表外鍵
}
@OneToMany和@ManyToOne
- 公司(組織)表相對於部門表是被控方,只需在被控方寫mappedBy,其值為主控方中引用的外鍵對象的名稱。
@Entity
@Table(name = "costume_organization")
public class Organization extends AbstractEntity {
private static final long serialVersionUID = 1L;
@Column(nullable = false, length = 50)
private String name; // 組織名稱
@OneToMany(mappedBy = "organization")
private Set<Department> departmentSet; // 部門集合
}
- 部門表相對於公司(組織)表是主控方,在主控方只需寫@ManyToOne即可,其對象名為被控表中mappedBy中的值。
- 同時需要注意,如果需要將公司表對象或者部門表對象轉為JSON數據的時候,為了防止出現無限循環包含對方,需要在部門表(多的一方)的引用公司表(少的一方)對象的set方法上寫上注解@JsonBackReference
@Entity
@Table(name = "costume_department")
public class Department extends AbstractEntity {
private static final long serialVersionUID = 1L;
@Column(nullable = false, length = 50)
private String name; // 部門名稱
@ManyToOne(optional = false)
private Organization organization; // 組織外鍵
@ManyToMany
private Set<Member> memberSet; // 用戶表外鍵
public Organization getOrganization() {
return organization;
}
@JsonBackReference
public void setOrganization(Organization organization) {
this.organization = organization;
}
}
@ManyToMany
- 在多對多的情況下,如部門表和員工表之間的關系(暫不去深究一個員工是否能有多個部門的身份)。
- 部門表和員工表只需在引用對象集合上注明@ManyToMany即可,其中部門表的寫法如上段代碼,員工表的寫法如下段代碼。
- 在多對多的映射中會生成一張中間表,其表名和字段名均有默認的命名規則,若需指定表名和字段名,只需在兩者的一方或雙方寫上@JoinTable注解即可,詳情如下代碼段,表名屬性name=”table_name”,與joinColumns屬性是同級屬性,即寫在其前即可。
- 同時需要注意,如果需要將員工表對象或者部門表對象轉為JSON數據的時候,為了防止出現無限循環包含對方,需要在一方的引用對方對象的set方法(Set對象的set方法)上寫上注解@JsonBackReference
@Entity
@Table(name = "costume_member")
public class Member extends AbstractEntity {
private static final long serialVersionUID = 1L;
@Column(nullable = false, length = 20)
private String name;
@ManyToMany
@JoinTable(joinColumns = { @JoinColumn(name = "member_id") }, inverseJoinColumns = {
@JoinColumn(name = "department_id") }) //被控方表字段名
private Set<Department> departmentSet; // 部門表外鍵
public Set<Department> getDepartmentSet() {
return departmentSet;
}
@JsonBackReference
public void setDepartmentSet(Set<Department> departmentSet)
{
this.departmentSet = departmentSet;
}
}