EclipseLink合并了意外的级联

时间:2012-08-14 17:16:03

标签: jpa eclipselink

我有两个实体类user和device。

用户实体:

public class User {
    private Long userId;

    @OneToMany( mappedBy = "userId", fetch = FetchType.LAZY)
    private Collection<Device> deviceCollection;

和设备实体:

public class Device implements Serializable {
    @JoinColumn(name = "user_id", referencedColumnName = "user_id")
    @ManyToOne(optional = false, fetch = FetchType.LAZY)
    private User userId;

当我删除父用户后将先前分离的设备实体合并到实体管理器中时,(先前删除的)用户和设备都被重新插入到数据库中。用户或设备实体上没有级联注释;因此,我不希望重新插入用户实体,但确实如此;

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

提前致谢。

4 个答案:

答案 0 :(得分:0)

您在分离状态下所做的任何更改都没有可能的方法让会话管理器知道它,因此更改总是需要合并的新对象(如果您正在调用合并)

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

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

你能做的就像下面我在Eclipse Link的一个项目中使用了类似的关系

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);

答案 1 :(得分:0)

尝试将 insertable = false,updatable = false 添加到您的JoinColumn,例如

@JoinColumn(name = "user_id", referencedColumnName = "user_id", insertable=false, updatable=false)

答案 2 :(得分:0)

您应该使用版本号来防止实体被错误地恢复。这将强制执行异常,因为规范有点不清楚在未标记为全部或合并的关系上合并时应该发生什么。规范声明管理实体将同步到数据库,而处理合并的部分意味着在没有级联合并/所有选项的关系引用的偶数实体将在之后进行管理。这种行为可能不是预期的,但在澄清之前不应该依赖。

答案 3 :(得分:-1)

我遇到了同样的问题 我发现了一个关于此问题的错误:EntityManager.merge() cascading by default 但我真的不明白为什么这种行为永远不会解决。其中一个原因是我不使用EclipseLink(但这不是重点)

<强> 编辑:

克里斯,以“我不是专家”开头的评论,我认为这个论点是不正确的。我所理解的,只是那个没有cascade = MERGE或cascade = ALL的关系的实体,你可以导航,就是这样。

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