[英]JPA Updating Bidirectional Association
讓我們假設我們有以下實體:
@Entity
public class Department {
@OneToMany(mappedBy="department")
private List<Employee> employees;
}
@Entity
public class Employee {
@ManyToOne
private Department department
}
在更新中我們需要維護關系的兩個方面,這是可以理解的,如下所示:
Employee emp = new Employee();
Department dep = new Department();
emp.setDepartment(dep);
dep.getEmployees().add(emp);
一切都很好,直到現在。 問題是我應該如下所示在雙方應用合並,並且我避免第二次合並級聯?
entityManager.merge(emp);
entityManager.merge(dep);
或者正在合並擁有方? 這些合並也應該發生在Transaction或EJB中嗎? 或者在具有分離實體的簡單控制器方法上執行它就足夠了?
問題是我應該如下所示在雙方應用合並,並且我避免第二次合並級聯?
您可以使用級聯注釋元素將操作的效果傳播到關聯實體。 級聯功能最常用於父子關系。
如果這些關系已使用cascade
元素值cascade=MERGE
或cascade=ALL
注釋進行注釋,則merge
操作將級聯到由Department
關系引用的實體。
管理實體之間的雙向關系將基於關系的擁有方(Employee)
持有的引用而持久化。 開發人員有責任將內存引用保留在擁有方(Employee)
和反向(Department)
保持在更改時保持一致。 因此,使用以下一系列語句,關系將通過單個merge
同步到數據庫:
Employee emp = new Employee();
Department dep = new Department();
emp.setDepartment(dep);
dep.getEmployees().add(emp);
...
entityManager.merge(dep);
這些更改將在事務提交時傳播到數據庫。 當事務處於活動狀態時,使用EntityManager#flush方法,實體的內存中狀態也可以在其他時間同步到數據庫。
你有一個持久的操作(使用em.merge()
)。 堅持新雇員並不意味着該部門還堅持(你有沒有級聯),因此它會拋出一個異常,因為另一個原因(簡單地嘗試它,並發布除外)。為了避免這種情況,你要么添加一個層疊式,或堅持他們兩個(正如你在你的例子中所做的那樣)。
關於你的問題:考慮的唯一部分是擁有方。 在JPA 2.0規范中, Chapter 3 Entity Operations
=> 3.2.4 Syncrhonization to the Database
是以下內容:
管理實體之間的雙向關系將基於關系所屬方所持有的引用而持久化。 開發人員有責任保持內存引用保持在擁有方,而保持在反方的引用在更改時保持一致。 在單向一對一和一對多關系的情況下,開發人員有責任確保遵守關系的語義。[29]
與事務需求相關 :是的,您需要合並操作一個活動事務。 摘自JPA 2規范:
當使用具有事務范圍持久性上下文的實體管理器時,必須在事務環境中調用persist,merge,remove和refresh方法。 如果沒有事務上下文,則拋出javax.persistence.TransactionRequiredException。
關於如何啟動事務/如何設置事務:它取決於EntityManager
的類型(關於如何獲取事務的方式)。 在EJB中,對於通用情況,處理它更容易。 此外,根據merge方法的文檔, if invoked on a container-managed entity manager of type PersistenceContextType.TRANSACTION and there is no transaction
, if invoked on a container-managed entity manager of type PersistenceContextType.TRANSACTION and there is no transaction
拋出TransactionRequiredException。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.