让我们假设我们有以下实体:
@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中吗?或者在一个带有分离实体的简单控制器方法上做它就足够了?
问题是我应该如下所示在双方应用合并,并且我避免第二次合并级联?
您可以使用级联注释元素将操作的效果传播到关联实体。级联功能最常用于父子关系。
该 merge
操作级联到由关系引用的实体 Department
如果这些关系已被注释 cascade
元素价值 cascade=MERGE
要么 cascade=ALL
注解。
管理实体之间的双向关系将基于拥有方持有的引用而持久化 (Employee)
关系。开发人员有责任将内存中的引用保留在拥有方 (Employee)
和那些相反的方面 (Department)
当他们改变时彼此一致。因此,通过以下系列语句,关系将与单个数据库同步到数据库 merge
:
Employee emp = new Employee();
Department dep = new Department();
emp.setDepartment(dep);
dep.getEmployees().add(emp);
...
entityManager.merge(dep);
这些更改将在事务提交时传播到数据库。当事务处于活动状态时,实体的内存中状态可以在其他时间同步到数据库 EntityManager的#刷新 方法。
你有一个 坚持 操作(用 em.merge()
)。坚持新员工 不 意味着部门也是持久的(你没有级联),所以它会因为另一个原因而抛出异常(只需尝试并发布异常)。为了避免这种情况,你要么添加级联类型,要么保留它们两者(正如你在你的例子中所做的那样)。
关于你的问题:考虑的唯一部分是拥有方。
在JPA 2.0规范中, Chapter 3 Entity Operations
=> 3.2.4 Syncrhonization to the Database
是下面的:
管理实体之间的双向关系将保持不变
基于关系所属方面的参考。它是
开发人员有责任保持内存中的引用
在拥有方和那些与反方保持一致的方面
当他们改变时彼此相对。在单向一对一的情况下
和一对多的关系,这是开发人员的责任
确保关系的语义得到遵守。[29]
与交易的需要有关:是的,您需要合并操作一个活动的事务。摘自JPA 2规范:
必须在其中调用persist,merge,remove和refresh方法
具有a的实体管理器的事务上下文
使用事务范围的持久性上下文。如果没有
交易背景,
抛出javax.persistence.TransactionRequiredException。
关于如何开始交易/如何交易交易:它取决于交易的类型 EntityManager
(在你如何得到一个的方式)。在EJB中,对于通用情况,处理它更容易。另外,根据文件 合并方法,抛出TransactionRequiredException, if invoked on a container-managed entity manager of type PersistenceContextType.TRANSACTION and there is no transaction
。