Jpa 日食合并意外级联

Jpa 日食合并意外级联,jpa,eclipselink,Jpa,Eclipselink,我有两个实体类user和device 用户实体: public class User { private Long userId; @OneToMany( mappedBy = "userId", fetch = FetchType.LAZY) private Collection<Device> deviceCollection; 删除父用户后,将以前分离的设备实体合并到实体管理器中时,(以前删除的)用户和设备都会重新插入数据库。用户或设备实体上没有级联

我有两个实体类user和device

用户实体:

public class User {
    private Long userId;

    @OneToMany( mappedBy = "userId", fetch = FetchType.LAZY)
    private Collection<Device> deviceCollection;
删除父用户后,将以前分离的设备实体合并到实体管理器中时,(以前删除的)用户和设备都会重新插入数据库。用户或设备实体上没有级联注释;因此,我不希望重新插入用户实体,但它确实插入了

如何防止合并操作级联到用户实体


提前感谢。

您在分离状态下所做的任何更改都无法让会话管理器知道,因此对于它来说,更改始终是需要合并的新对象(如果您正在调用merge)

所以,当您调用merge时,它将从数据库中加载它,这样您的对象将具有Prev+新更改。这就是为什么会发生上述行为

您可以做的是首先在会话中加载实体并应用更改,然后调用merge

您可以做的事情如下所示,我在我的一个项目中使用了与Eclipse链接类似的关系

Query query = entityManager
            .createNamedQuery("User.FindByUserId");
    User fromDatabase = null;
    try {
        query.setParameter("userId", device.getUser().getUserId());
        fromDatabase = (User) query.getSingleResult();

    } catch (NoResultException noResultException) {
        // There is no need to do anything here.
    }
    if (fromDatabase == null) {
        User user= entityManager.merge(device.getUser());
         device.setUser(user);
    } else {
        device.setUser(user);
    }
    entityManager.persist(device);

尝试将insertable=false,updateable=false添加到JoinColumn中,例如

@JoinColumn(name = "user_id", referencedColumnName = "user_id", insertable=false, updatable=false)
我也有同样的问题 我发现了一个错误: 但我真的不明白为什么这种行为从来没有得到纠正。这是我不使用EclipseLink的原因之一(但这不是重点)

编辑:

克里斯,以“我不是专家”开头的评论,我认为放在头脑里的论点是不对的。据我所知,这只是一个实体,它与一个没有cascade=MERGE或cascade=ALL的关系,你可以导航,仅此而已


否则为什么要使用合并注释?这没有意义。

您应该使用版本号来防止实体被错误地重拾。这将强制执行一个异常,因为规范对于在未标记为cascade all或merge的关系上进行合并时应该发生什么不太清楚。规范规定,托管实体将与数据库同步,而处理合并的部分暗示,即使没有级联合并/所有选项的关系引用的实体也将在之后进行管理。这种行为可能并非本意,但在澄清之前不应依赖

但我希望它不会合并用户实体,因为没有指定级联选项。这是否意味着合并操作总是级联,并且无法关闭它?同样,它是特定于提供程序的,但对我有效的是@OneToMany(cascade={}),这就像指定cascade NONE一样。请尝试并让我知道。我尝试将cascade={}放在用户实体(OneToMany)和设备实体(ManyToOne)上;效果是一样的。用户实体仍被重新插入。这也没有帮助。用户行仍被插入。正如错误中的最后一篇文章所述,规范规定在未标记为级联合并的关系上引用分离的实体仍将返回托管实例。它没有说明托管实例的含义。如果这是阻止你尝试Eclispelink的唯一原因,我怀疑你是否真的给了它一个机会。如果X引用Y,则X'引用托管Y'。如果Y'是被管理的,那么它就是与数据库同步的东西。如果Y'是非托管对象,规范将其完全打开,而大多数用户理解并希望托管Y'实例(如果存在)。您可以使用级联合并选项将更改放入现有的Y'实例中-如果Y'已经存在,则合并X不会将Y合并到Y'中。规范没有一个托管实体的概念,您只需浏览即可。它是被管理的,或者不是。我认为这是EclipseLink中的一个bug。
@JoinColumn(name = "user_id", referencedColumnName = "user_id", insertable=false, updatable=false)