JPA-删除双向关系的元素 [英] JPA - Removing of elements of a bidirectional Relationship
问题描述
为什么在持久性上下文中仅管理关系的一侧,我为什么要删除双向关系的元素(示例I)?当我有单向关系不起作用时(请参见示例II).为什么?
Why can i remove elements of a bidirectional relation although only one side of the relation is managed in persistence context (Example I)? When i have an unidirectional Relationship that doesn't work (see Example II). Why?
实体:
@Entity
Class User {
...
@OneToMany(mappedBy = "user")
private List<Process> processes;
@OneToOne // Unidirectional
private C c;
...
@PreRemove
private void preRemove() {
for (Process p : processes) {
p.internalSetUser(null);
}
}
...
}
@Entity
Class Process {
...
@ManyToOne
private User user;
...
@PreRemove
protected void preRemove() {
if (this.user != null) {
user.internalRemoveProcess(this);
}
}
...
}
@Entity
Class C {
}
示例I:
// Create User u1 with Processes p1, p2
tx.start();
// Only u1 is manged in persistence context and no process
userFacade.delete(u1); // There following is called: >> em.remove(em.merge(u1)); // Works
tx.commit();
示例II:
// Create User u and Object C c, establish their relation.
tx.start();
cFacade.remove(c); //>>MySQLIntegrityConstraintViolationException,foreign key constraint fails
ty.commit();
在第一个示例中,我使用这些内部方法在每种情况下设置关系的另一端,但是我认为在持久性上下文中无法管理该另一端吗?当我更改用户的流程并保存用户时,除非我使用cascade.MERGE或两者都在事务中加载并因此在pc中进行管理,否则不会更新该流程.那为什么要删除呢?
In the first example i use these internal methods to set in each case the other side of the relation but this other side is not managed in persistence context i think?! When i change a process of a user and save the user, the process is not updated unless i uses cascade.MERGE or if both are loaded in a transaction and therefor are managed in pc. So why does the removing work?
推荐答案
在示例II中,我想您必须在删除c
之前先调用user.setC(null)
.
In Example II, I guess you would have to call user.setC(null)
before deleting the c
.
在示例I中,这是我的理解.首先,您要合并u1
,以便将u1'
加载到PC中,并将u1
的状态复制到u1'
(仅此而已,因为您没有级联MERGE
),然后将其返回.然后,调用remove(在u1'
上),调用preRemove
并更改p1'
和p2'
.因此它们很脏,将在刷新时适当更新(将FK设置为NULL
),而将删除u1'
.一切正常.
In Example I, here is my understanding. You are first merging u1
so a u1'
gets loaded into the PC and the state of u1
is copied to u1'
(and that's all since you're not cascading MERGE
), which is then returned. Then you call remove (on u1'
), the preRemove
gets called and changes p1'
and p2'
. They are thus dirty and will get updated appropriately on flush (setting the FK to NULL
), while u1'
will be deleted. And everything works.
以防万一,这是JPA 2.0规范中合并操作的语义:
Just in case, here are the semantics of the merge operation from the JPA 2.0 specification:
3.2.7.1合并独立的实体状态
合并操作允许 脱离状态的传播 实体到持久实体 由实体经理管理.
3.2.7.1 Merging Detached Entity State
The merge operation allows for the propagation of state from detached entities onto persistent entities managed by the entity manager.
合并操作的语义 应用于实体X的情况如下:
The semantics of the merge operation applied to an entity X are as follows:
- 如果
X
是独立实体,则将X
的状态复制到 预先存在的管理实体实例 具有相同标识或新标识的X'
已创建X
的受管副本X'
. - 如果
X
是新的实体实例,则新的管理实体实例X'
是 创建并复制X
的状态 进入新的受管实体实例X'
. - 如果
X
是已删除的实体实例,则IllegalArgumentException
将是 由合并操作(或 事务提交将失败). - 如果
X
是受管实体,则合并操作将忽略它, 但是,合并操作是 级联到所引用的实体X
中的关系,如果这些 关系已被注释为 级联元素值cascade=MERGE
或cascade=ALL
注释. - 对于由
X
中的关系引用的所有具有X
关系的实体Y
级联元素值cascade=MERGE
或cascade=ALL
,Y
被合并 递归为Y'
.对于所有这样的Y
X
引用的X'
设置为 参考Y'
. (请注意,如果X
是 托管,然后X
是与以下对象相同的对象X'
.) - 如果
X
是合并到X'
的实体,并且引用了另一个实体Y
,其中cascade=MERGE
或 未指定cascade=ALL
,则 相同关联的导航 从X'
产生对a的引用 托管对象Y'
具有相同的 永久身份为Y
.
- If
X
is a detached entity, the state ofX
is copied onto a pre-existing managed entity instanceX'
of the same identity or a new managed copyX'
ofX
is created. - If
X
is a new entity instance, a new managed entity instanceX'
is created and the state ofX
is copied into the new managed entity instanceX'
. - If
X
is a removed entity instance, anIllegalArgumentException
will be thrown by the merge operation (or the transaction commit will fail). - If
X
is a managed entity, it is ignored by the merge operation, however, the merge operation is cascaded to entities referenced by relationships fromX
if these relationships have been annotated with the cascade element valuecascade=MERGE
orcascade=ALL
annotation. - For all entities
Y
referenced by relationships fromX
having the cascade element valuecascade=MERGE
orcascade=ALL
,Y
is merged recursively asY'
. For all suchY
referenced byX
,X'
is set to referenceY'
. (Note that ifX
is managed thenX
is the same object asX'
.) - If
X
is an entity merged toX'
, with a reference to another entityY
, wherecascade=MERGE
orcascade=ALL
is not specified, then navigation of the same association fromX'
yields a reference to a managed objectY'
with the same persistent identity asY
.
持久性提供程序不得 合并标记为LAZY的字段,这些字段没有 被获取:它必须忽略这样的 合并时的字段.
The persistence provider must not merge fields marked LAZY that have not been fetched: it must ignore such fields when merging.
实体必须由
持久性运行时实现
在合并操作期间和/或
刷新或提交时间.离席期间
Version
列中没有
进行的附加版本检查
持久性提供程序运行时
在合并操作期间.
Any Version
columns used by the
entity must be checked by the
persistence runtime implementation
during the merge operation and/or at
flush or commit time. In the absence
of Version
columns there is no
additional version checking done by
the persistence provider runtime
during the merge operation.
参考
- JPA 2.0规范
- 3.2.7.1合并独立的实体状态
- JPA 2.0 Specification
- 3.2.7.1 Merging Detached Entity State
这篇关于JPA-删除双向关系的元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
Reference