JPA-删除双向关系的元素 [英] JPA - Removing of elements of a bidirectional Relationship

查看:118
本文介绍了JPA-删除双向关系的元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么在持久性上下文中仅管理关系的一侧,我为什么要删除双向关系的元素(示例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=MERGEcascade=ALL 注释.
  • 对于由X中的关系引用的所有具有X关系的实体Y 级联元素值cascade=MERGEcascade=ALLY被合并 递归为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 of X is copied onto a pre-existing managed entity instance X' of the same identity or a new managed copy X' of X is created.
  • If X is a new entity instance, a new managed entity instance X' is created and the state of X is copied into the new managed entity instance X'.
  • If X is a removed entity instance, an IllegalArgumentException 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 from X if these relationships have been annotated with the cascade element value cascade=MERGE or cascade=ALL annotation.
  • For all entities Y referenced by relationships from X having the cascade element value cascade=MERGE or cascade=ALL, Y is merged recursively as Y'. For all such Y referenced by X, X' is set to reference Y'. (Note that if X is managed then X is the same object as X'.)
  • If X is an entity merged to X', with a reference to another entity Y, where cascade=MERGE or cascade=ALL is not specified, then navigation of the same association from X' yields a reference to a managed object Y' with the same persistent identity as Y.

持久性提供程序不得 合并标记为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合并独立的实体状态
    • Reference

      • JPA 2.0 Specification
        • 3.2.7.1 Merging Detached Entity State
        • 这篇关于JPA-删除双向关系的元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆