[英]Merging a managed entity on the @ManyToOne side
下面給出了從Department
到Employee
的一對多關系。
部門(母公司):
@OneToMany(mappedBy = "department", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private List<Employee> employeeList = new ArrayList<Employee>(0);
員工(孩子):
@JoinColumn(name = "department_id", referencedColumnName = "department_id")
@ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH, CascadeType.DETACH})
private Department department;
合並一個托管實體(子代碼),如下所示(在EJB中使用CMT),
Employee employee = entityManager.find(Employee.class, 1L);
employee.setDepartment(department); // department is supplied by a client.
employee.setEmployeeName("xyz");
entityManager.merge(employee);
不更新數據庫表中相應的員工行。 僅當從Employee
的子@ManyToOne
關系中刪除CascadeType.MERGE
時才會發生這種情況。
為什么表中的行不會更新? CascadeType.MERGE
關於這個例子的唯一目的是什么?
我目前正在使用具有JPA 2.1的EclipseLink 2.6.0。
在您的情況下,您需要從子端刪除Cascade:
@JoinColumn(name = "department_id", referencedColumnName = "department_id")
@ManyToOne(fetch = FetchType.LAZY)
private Department department;
並確保設置關聯的兩側:
Employee employee = entityManager.find(Employee.class, 1L);
employee.setDepartment(department);
employee.setEmployeeName("xyz");
department.getEmployeeList().add(employee);
entityManager.merge(department);
這個代碼是有風險的,因為您正在關聯一個分離的部門實例,然后可能會有一個獨立的員工集合。 如果具有新xyz名稱的當前員工位於該列表中,則其更改將被分離實例的名稱覆蓋。
例如,在你調用employee.setDepartment(department)之后; 員工(1L) - >部門' - >員工(1L)'
在employee(1L)實例上調用合並將不會執行任何操作,因為名稱更改已經可見,但它會傳送到部門。 合並部門然后級聯到具有舊名稱的雇員(1L)'實例。 如果您檢查了employee.getEmployeeName()的值,您會看到合並導致它重置,這可能是您沒有看到數據庫更新的原因。
不調用merge雖然不是一個選項,因為你仍然有員工引用一個獨立的部門,這應該是一個例外情況。 這就是提供者發布插入的原因。
據推測,您在關系上有級聯合並集,因為客戶端提供的部門對象也可能包含員工更改。 如果是這樣,要同步這些更改並更改employeeName,您將使用:
Department managedDepartment = entityManager.merge(department);
Employee employee = entityManager.find(Employee.class, 1L);
employee.setDepartment(managedDepartment);
managedDepartment.getEmployeeList().add(employee);
employee.setEmployeeName("xyz");
如果員工不在那里,這兩者都可以將員工添加到部門,如果是,則仍然會更改名稱。
我也閱讀了其他答案和bugzilla問題,但我仍然相信這種行為是一個錯誤,或者至少是一個缺失的功能。
請按照我的想法:
Employee employee = entityManager.find(Employee.class, 1L);
員工是管理實體;
employee.setDepartment(department); // department is supplied by a client.
部門是一個獨立的實體;
entityManager.merge(employee);
由於員工已經被管理,合並員工只會觸發部門的合並級聯。
所以:
merge(department)
現在也管理着沮喪; 這將觸發員工級聯:
merge(employee1)
merge(employee2)
...
merge(employeeN)
但有兩種不同的情況:
在這種情況下,員工是否包含在employeeList中?
三種可能性(取決於其他變量,如flush-mode,auto-commit,......):
延遲加載時,我認為“bug”可能就在這里: 不應該在同一個EntityManager中有兩個相同實體的托管實例 。
我想不出一個反例。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.