5

我有两个实体类用户和设备。

用户实体:

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

4 回答 4

0

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

@JoinColumn(name = "user_id", referencedColumnName = "user_id", insertable=false, updatable=false)
于 2012-08-15T01:05:46.570 回答
0

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

因此,当您调用合并时,它将从数据库中加载它,因此您的对象将具有 Prev+ 新更改。所以这就是为什么提到的行为正在发生。

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

您可以做的如下所示我在我的一个项目中使用 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);
于 2012-08-14T17:29:31.703 回答
0

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

于 2012-09-11T17:47:44.767 回答
-1

我遇到了同样的问题,我发现了一个关于此的错误:EntityManager.merge() 默认为级联, 但我真的不明白为什么这种行为永远无法修复。这是我不使用 EclipseLink 的原因之一(但这不是重点)

编辑:

克里斯,以“我不是专家”开头的评论放在头脑中的论点是不正确的,我认为。据我了解,它只是具有没有 cascade=MERGE 或 cascade=ALL 的关系的实体,您可以导航,仅此而已。

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

于 2012-09-11T13:26:55.653 回答