我有两个实体类用户和设备。
用户实体:
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;
删除父用户后,当我将以前分离的设备实体合并到实体管理器中时,(以前删除的)用户和设备都将重新插入到数据库中。用户或设备实体上没有级联注释;因此,我不希望重新插入用户实体,但它确实如此;
如何防止合并操作级联到用户实体?
提前谢谢。
您在分离状态下所做的任何更改都不可能让会话管理器知道它,因此对于它来说,更改始终是需要合并的新对象(如果您正在调用合并)
因此,当您调用 merge 时,它将从数据库加载它,因此您的对象将具有 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);
尝试将 insertable=false, updatable=false 添加到您的 JoinColumn,例如
@JoinColumn(name = "user_id", referencedColumnName = "user_id", insertable=false, updatable=false)
您应该使用版本号来防止实体被错误地恢复。 这将强制出现异常,因为规范有点不清楚在合并未标记为级联全部或合并的关系时应该发生什么。 规范指出托管实体将同步到数据库,而处理合并的部分意味着,即使是没有级联合并/所有选项的关系引用的实体也将在之后进行管理。 这种行为可能不是本意,但在澄清之前不应依赖此行为。
我遇到了同样的问题我发现了一个关于这个的错误:默认情况下 EntityManager.merge() 级联但我真的不明白为什么这种行为从未得到解决。这是我不使用EclipseLink的原因之一(但这不是这里的重点)
编辑:
克里斯,我认为以"我不是专家"开头的评论是不对的。我的理解是,这只是那个没有级联=合并或级联=全部关系的实体,你可以导航,仅此而已。
否则为什么要使用合并注释?这没有意义。