简体   繁体   English

JPA更新双向关联

[英]JPA Updating Bidirectional Association

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? 这些合并也应该发生在Transaction或EJB中吗? Or doing it on a simple controller method with detached entities is enough? 或者在具有分离实体的简单控制器方法上执行它就足够了?

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. 如果这些关系已使用cascade元素值cascade=MERGEcascade=ALL注释进行注释,则merge操作将级联到由Department关系引用的实体。

Bidirectional relationships between managed entities will be persisted based on references held by the owning side (Employee) of the relationship. 管理实体之间的双向关系将基于关系的拥有方(Employee)持有的引用而持久化。 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. 开发人员有责任将内存引用保留在拥有方(Employee)和反向(Department)保持在更改时保持一致。 So, with below series of statements, the relationship will be synchronized to the database with a single merge : 因此,使用以下一系列语句,关系将通过单个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#flush method. 当事务处于活动状态时,使用EntityManager#flush方法,实体的内存中状态也可以在其他时间同步到数据库。

You have there a persist operation (made with em.merge() ). 你有一个持久的操作(使用em.merge() )。 Persisting a new employee does not mean 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). 坚持新雇员并不意味着该部门还坚持(你有没有级联),因此它会抛出一个异常,因为另一个原因(简单地尝试它,并发布除外)。为了避免这种情况,你要么添加一个层叠式,或坚持他们两个(正如你在你的例子中所做的那样)。

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. 当使用具有事务范围持久性上下文的实体管理器时,必须在事务环境中调用persist,merge,remove和refresh方法。 If there is no transac- tion context, the javax.persistence.TransactionRequiredException is thrown. 如果没有事务上下文,则抛出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). 关于如何启动事务/如何设置事务:它取决于EntityManager的类型(关于如何获取事务的方式)。 In EJB it is much easier to handle that for generic situations. 在EJB中,对于通用情况,处理它更容易。 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 . 此外,根据merge方法的文档, if invoked on a container-managed entity manager of type PersistenceContextType.TRANSACTION and there is no transactionif 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM