我当前正在努力删除一个涉及各种关系的实体(只有@ManyToOne
) - 但是,Hibernate不会删除任何内容 - 在调用em.remove
后,一切都保持不变。
我有5个实体(E1 - E5
),引用有问题的实体(E6
),如下所示:
@Entity
public class EX {
@OneToMany(mappedBy = "eX", fetch = FetchType.EAGER, cascade = { CascadeType.PERSIST, CascadeType.REMOVE })
private Set<E6> e6s;
}
E6
本身具有相反的@ManyToOne
关系:
public class E6{
@ManyToOne(optional = false)
private E1 e1;
@ManyToOne(optional = false)
private E2 e2;
@ManyToOne(optional = false)
private E3 e3;
@ManyToOne(optional = false)
private E4 e4;
@ManyToOne(optional = false)
private E5 e5;
}
(遗漏了ID,其他列等......)
每当我致电em.remove(instanceOfE6)
时,只需无。我添加了Hibernate SQL-Output,无法看到执行DELETE
查询的单次尝试。
由于删除可能发生在ajax请求和 fresh EntityManager中,我在删除之前添加了一个合并调用,导致其他人获得 Entity unmanaged Exception :
em.remove(em.merge(instanceOfE6));
但没有。国家保持不变。
所以我尝试在删除实体之前添加@PreRemove
方法来清除所有关系...方法永远不会被调用。
我尝试了各种级联操作(包括Cascade.ALL
) - 但由于我需要的只是移除和持久,所以它也应该正常工作。
我考虑过使用原生的Delete语句(每个实体都有一个代理ID,因此最有可能工作) - 但由于所有事情都是在AJAX调用中发生的,所以我不想使用它,因为我想要更新Persistence-Cache而不重新获取每个涉及的实体......
有什么想法吗?
如果您需要更多来源,请给我发表评论。
我还试图从所有关系中删除有问题的实体(对象明智),并在剩下的一个实体上调用em.merge()
,希望hibernate会消除未链接的实体 - 没有运气。
答案 0 :(得分:14)
我想出了问题 - 实际上有两个问题:(如果有人遇到类似的问题,请留下这个问题)
正如我所提到的,删除应该发生在ajax请求中。因此,简单的调用
em.remove(instanceOfE6);
导致java.lang.IllegalArgumentException: Removing a detached instance
例外。所以,我尝试了使用merge的方法:
em.remove(em.merge(instanceOfE6));
没有产生错误 - 但简单没有工作。我启用了hibernate的跟踪日志记录,如本文所述:JPA/Hibernate remove entity sometimes not working以找出问题所在,实际上,尝试删除实体导致:
TRACE [org...DefaultPersistEventListener] un-scheduling entity deletion ...
显然要删除的实体仍然连接到其他实体,这导致hibernate中止删除的问题,所以我试图在删除之前删除关系。
正如您从E6
的示例中看到的,我使用了@ManyToOne(optional = false)
,这意味着我无法将传出引用设置为null,或者在调用merge
时会导致异常。
我第一次尝试清理关系只是&#34;清理集合&#34;,因为我认为不需要清理我要删除的实体的传出关系。事实并非如此,但稍后我将详细介绍这一点:
所以,代码现在看起来像
instanceOfE6.getE1().getE6s().remove(instanceOfE6);
instanceOfE6.getE2().getE6s().remove(instanceOfE6);
instanceOfE6.getE3().getE6s().remove(instanceOfE6);
instanceOfE6.getE4().getE6s().remove(instanceOfE6);
instanceOfE6.getE5().getE6s().remove(instanceOfE6);
em.remove(em.merge(instanceOfE6));
同样的问题:删除已中止。我错过了一个显而易见的事实,那就是呼叫merge
。恢复我刚刚删除的集合中的条目,因为instanceOfE6 STILL在其他实体上没有可引用的引用。因此删除再次中止。
最后解决方案。是在删除引用和最终删除之前进行合并:
if (!em.contains(instanceOfE6)){
instanceOfE6 = em.merge(instanceOfE6);
}
instanceOfE6.getE1().getE6s().remove(instanceOfE6);
instanceOfE6.getE2().getE6s().remove(instanceOfE6);
instanceOfE6.getE3().getE6s().remove(instanceOfE6);
instanceOfE6.getE4().getE6s().remove(instanceOfE6);
instanceOfE6.getE5().getE6s().remove(instanceOfE6);
em.remove(instanceOfE6);
我不太确定我是否100%准确地解释了所有内容,但至少我可以通过来回更改代码来重现并修复问题。