Java JPA 更新双向关联
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20068742/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
JPA Updating Bidirectional Association
提问by ChrisGeo
Lets assume we have the following Entities:
假设我们有以下实体:
@Entity
public class Department {
@OneToMany(mappedBy="department")
private List<Employee> employees;
}
@Entity
public class Employee {
@ManyToOne
private Department department
}
It is understandable on an update that we need to maintain both sides of the relationship as follows:
在更新中,我们需要维护双方的关系如下,这是可以理解的:
Employee emp = new Employee();
Department dep = new Department();
emp.setDepartment(dep);
dep.getEmployees().add(emp);
All good up till now. The question is should I apply merge on both sides as follows, and an I avoid the second merge with a cascade?
到目前为止一切都很好。问题是我是否应该按如下方式在两侧应用合并,并且避免使用级联进行第二次合并?
entityManager.merge(emp);
entityManager.merge(dep);
Or is merging the owning side enough? Also should these merges happen inside a Transaction or EJB? Or doing it on a simple controller method with detached entities is enough?
或者合并拥有方就足够了?这些合并也应该发生在事务或 EJB 中吗?或者在具有分离实体的简单控制器方法上进行就足够了?
采纳答案by Debojit Saikia
The question is should I apply merge on both sides as follows, and an I avoid the second merge with a cascade?
问题是我是否应该按如下方式在两侧应用合并,并且避免使用级联进行第二次合并?
You can use the cascade annotation element to propagate the effect of an operation to associated entities. The cascade functionality is most typically used in parent-child relationships.
您可以使用级联注释元素将操作的效果传播到关联实体。级联功能最常用于父子关系。
The merge
operation is cascaded to entities referenced by relationships from Department
if these relationships have been annotated with the cascade
element value cascade=MERGE
or cascade=ALL
annotation.
该merge
操作级联到由关系引用的实体Department
,如果这些关系已经标注了该cascade
元素的值cascade=MERGE
或cascade=ALL
注释。
Bidirectional relationships between managed entities will be persisted based on references held by the owning side (Employee)
of the relationship. It is the developer's responsibility to keep the in-memory references held on the owning side (Employee)
and those held on the inverse side (Department)
consistent with each other when they change. So, with below series of statements, the relationship will be synchronized to the database with a single merge
:
受管实体之间的双向关系将基于(Employee)
关系拥有方持有的引用而持久化。开发人员有责任在更改时保持拥有方持有的内存引用(Employee)
和反向方持有的内存引用(Department)
彼此一致。因此,使用以下系列语句,关系将通过单个 同步到数据库merge
:
Employee emp = new Employee();
Department dep = new Department();
emp.setDepartment(dep);
dep.getEmployees().add(emp);
...
entityManager.merge(dep);
These changes will be propagated to database at transaction commit. The in-memory state of the entities can be synchronized to the database at other times as well when a transaction is active by using the EntityManager#flushmethod.
这些更改将在事务提交时传播到数据库。通过使用EntityManager#flush方法,在事务处于活动状态时,实体的内存状态也可以在其他时间同步到数据库。
回答by Andrei I
You have there a persistoperation (made with em.merge()
). Persisting a new employee does notmean that the department is also persisted (you have no cascading), so it will throw an exception because of another reason (simply try it and post the Exception).To avoid that, you either add a cascading type, or persist both of them (as you made in your example).
你有一个持久化操作(用 制作em.merge()
)。坚持新雇员并不能意味着该部门还坚持(你有没有级联),因此它会抛出一个异常,因为另一个原因(简单地尝试它,并发布除外)。为了避免这种情况,你要么添加一个层叠式,或坚持他们两个(正如你在你的例子中所做的那样)。
About your question: the only part considered would be the owning side.
In the JPA 2.0 spec, Chapter 3 Entity Operations
=> 3.2.4 Syncrhonization to the Database
is the follwoing:
关于您的问题:唯一考虑的部分是拥有方。在 JPA 2.0 规范中,Chapter 3 Entity Operations
=>3.2.4 Syncrhonization to the Database
是以下内容:
Bidirectional relationships between managed entities will be persisted based on references held by the owning side of the relationship. It is the developer's responsibility to keep the in-memory references held on the owning side and those held on the inverse side consistent with each other when they change. In the case of unidirectional one-to-one and one-to-many relationships, it is the developer's responsibil- ity to insure that the semantics of the relationships are adhered to.[29]
受管实体之间的双向关系将基于关系拥有方持有的引用而持久化。开发人员有责任在更改时保持拥有方持有的内存引用和反向方持有的内存引用彼此一致。在单向一对一和一对多关系的情况下,开发人员有责任确保遵守关系的语义。 [29]
Related to the need of a transaction: yes, you need for the merge operation an active transaction. Excerpt from JPA 2 specification:
与事务需要相关:是的,您需要为合并操作创建一个活动事务。摘自 JPA 2 规范:
The persist, merge, remove, and refresh methods must be invoked within a transaction con- text when an entity manager with a transaction-scoped persistence context is used. If there is no transac- tion context, the javax.persistence.TransactionRequiredException is thrown.
当使用具有事务范围持久性上下文的实体管理器时,必须在事务上下文中调用persist、merge、remove 和refresh 方法。如果没有事务上下文,则抛出 javax.persistence.TransactionRequiredException。
On how a transaction is started/how you starat a transaction: it depends on the type of the EntityManager
(on the way how you get one). In EJB it is much easier to handle that for generic situations. Also, according to the documentation of the merge method, a TransactionRequiredException is thrown, if invoked on a container-managed entity manager of type PersistenceContextType.TRANSACTION and there is no transaction
.
关于如何开始交易/如何开始交易:这取决于交易的类型EntityManager
(在您获得交易的方式上)。在 EJB 中,处理一般情况要容易得多。此外,根据合并方法的文档,会抛出 TransactionRequiredException if invoked on a container-managed entity manager of type PersistenceContextType.TRANSACTION and there is no transaction
。