6.1 深度依賴管理

還有一些關於@OneToMany註解之類的更有用和有趣的東西。它們都有4個常用選項:

  • 級聯= CascadeType.ALL
  • orphanRemoval = 真
  • fetch = FetchType.LAZY

現在我們將更詳細地分析它們。我們將從最有趣的 - CascadeType開始。如果我們更改主要實體,此參數確定依賴實體應該發生什麼。

JPA規範對該參數有如下取值:

  • 全部
  • 堅持
  • 合併
  • 消除
  • 刷新
  • 分離

但是,Hibernate 將此規範擴展為三個更多選項:

  • 複製
  • SAVE_UPDATE

當然,數據庫和它們的 CONSTRANIS 有很強的相似性。但是,也有區別。Hibernate 試圖盡可能地隱藏與數據庫的實際工作,因此這些 Hibernate Cascades 正是關於 Entity 對象的。

6.2 級聯類型

cascade 參數描述瞭如果我們更改它們的父對象(主對象),依賴對象應該發生什麼。大多數情況下,此參數與描述對象依賴關係的註釋一起使用:

例子:

OneToOne(cascade = CascadeType.ALL)

或者像這樣:

@ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})

也可以寫成單獨的註解:

@Cascade({ org.hibernate.annotations.CascadeType.ALL })

現在讓我們更多地討論這些註釋的含義。

6.3 全部、堅持、合併

CascadeType.ALL意味著我們對父對象執行的所有操作都必須對其依賴對象重複。

CascadeType.PERSIST意味著如果我們將父對象保存到數據庫中,那麼必須對它的依賴對像做同樣的事情。例子:


@Entity
@Table(name="employee")
class Employee {
   @Column(name="id")
   public Integer id;
 
   @OneToOne(cascade = CascadeType.PERSIST, mappedBy="task")
   private EmployeeTask task;
}

使用此類的示例:


Employee director = new Employee();
EmployeeTask task = new EmployeeTask();
director.task = task;
 
session.persist(director);
session.flush();

我們只保存一個Employee類型的對象,它的依賴對象EmployeeTask會自動保存到數據庫中。

CascadeType.MERGE意味著如果我們更新數據庫中的父對象,則必須對其依賴對象進行相同的操作。

6.4 移除、刪除、分離

CascadeType.REMOVE意味著如果我們刪除數據庫中的父對象,那麼必須對它的依賴對像做同樣的事情。

CascadeType.DELETE意思一樣。這些是同義詞。只是規格不同而已。

CascadeType.DETACH意味著如果我們從會話中刪除父對象,那麼必須對它的依賴對象進行同樣的操作。例子:


@Entity
@Table(name="employee")
class Employee {
   @Column(name="id")
   public Integer id;
 
   @OneToOne(cascade = CascadeType.DETACH, mappedBy="task")
   private EmployeeTask task;
}

使用此類的示例:


Employee director = new Employee();
EmployeeTask task = new EmployeeTask();
director.task = task;
director.task = task;
session.flush();
 
assertThat(session.contains(director)).isTrue();
assertThat(session.contains(task)).isTrue();
 
session.detach(director);
 
assertThat(session.contains(director)).isFalse();
assertThat(session.contains(task)).isFalse();

CascadeType.REFRESHCascadeType.SAVE_UPDATE以與我們預期相同的方式工作——它們將對父對象執行的操作複製到其從屬對象。

6.5 孤兒刪除選項

有時您可能還會遇到參數orphan。這是孤兒移除的縮寫。它用於確保不存在沒有父實體的子實體。

OneToOne(orphan = true)

如果此參數設置為true,則子實體消失後將被刪除所有鏈接. 它與 . 不完全相同Cascade.REMOVE

您可能會遇到多個父實體引用一個子實體的情況。那麼有益的是它不會隨著父實體的刪除而被刪除,但前提是對它的所有引用都被取消。

假設你有一堂課:


@Entity
@Table(name="user")
class Employee {
   @Column(name="id")
   public Integer id;
 
   @OneToMany(cascade = CascadeType.ALL, orphan = true)
   @JoinColumn(name = "employee_id")
   private Set<EmployeeTask> tasks = new HashSet<EmployeeTask>();
}


Employee director = session.find(Employee.class, 4);
EmployeeTask task = director.tasks.get(0);
director.tasks.remove(task)
session.persist(director);
session.flush();

EmployeeTask 對象將被刪除,因為沒有留下任何引用。同時,沒有人刪除父對象。

6.6 獲取選項

fetch 選項允許您控制依賴對象的加載方式。它通常採用以下兩個值之一:

  • FetchType.LAZY
  • FetchType.EAGER

這是一個非常有趣的話題,有各種陷阱,所以我最好單獨講一講。