Hibernate EntityManager:删除引用的实体不工作

dog*_*ose 5 hibernate jpa cascade entitymanager

我当前正在努力删除一个涉及各种关系的实体(仅限@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;  
}
Run Code Online (Sandbox Code Playgroud)

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;
}
Run Code Online (Sandbox Code Playgroud)

(遗漏了ID,其他列等......)


每当我打电话时em.remove(instanceOfE6),根本没有任何反应.我添加了Hibernate SQL-Output,无法看到执行DELETEQuery 的单次尝试.

由于删除可以从ajax请求和新的 EntityManager发生,我在删除之前添加了一个合并调用,导致其他我获得实体非托管异常:

em.remove(em.merge(instanceOfE6));
Run Code Online (Sandbox Code Playgroud)

但没什么.国家保持不变.

所以我尝试@PreRemove在删除实体之前添加一个方法来清除所有关系...从不调用方法.

我尝试了各种级联操作(包括Cascade.ALL) - 但由于我需要的只是删除和持久,这应该也可以.


我想过使用一个原生的Delete语句(每个实体都有一个代理id,所以很可能会工作) - 但是因为所有事情都是在AJAX调用中发生的,所以我不想使用它,因为我想拥有更新Persistence-Cache而无需重新获取每个涉及的实体...

有任何想法吗?

如果您需要更多来源,请给我发表评论.


我还试图从所有关系中删除有问题的实体(对象明智),并调用em.merge()剩下的一个实体,希望hibernate能够消除未链接的实体 - 没有运气.

dog*_*ose 14

我想出了问题 - 实际上有两个问题:(如果有人遇到类似的问题,请留下这里)

正如我所提到的,删除应该发生在ajax请求中.因此,简单的呼唤

em.remove(instanceOfE6);
Run Code Online (Sandbox Code Playgroud)

导致java.lang.IllegalArgumentException: Removing a detached instance例外.所以,我尝试了使用merge的方法:

em.remove(em.merge(instanceOfE6));
Run Code Online (Sandbox Code Playgroud)

这没有产生错误 - 但简单不起作用.我启用了hibernate的跟踪日志记录,如本文所述:JPA/Hibernate删除实体有时无法弄清楚出了什么问题,实际上,尝试删除实体导致:

 TRACE [org...DefaultPersistEventListener] un-scheduling entity deletion ...
Run Code Online (Sandbox Code Playgroud)

显然,要删除的实体仍然连接到其他实体,这导致hibernate中止删除的问题,所以我试图在删除之前删除关系.正如您在示例中所看到的E6,我使用过@ManyToOne(optional = false),这意味着我无法将传出引用设置为null,否则在调用时会导致异常merge.

我第一次尝试清理关系只是"清理集合",因为我认为不需要清理我要删除的实体的传出关系.事实并非如此,但稍后我将详细介绍这一点:

所以,代码现在看起来像

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));
Run Code Online (Sandbox Code Playgroud)

同样的问题:删除中止.我错过了一个显而易见的事实,那就是召唤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);
Run Code Online (Sandbox Code Playgroud)

我不太确定我是否100%准确地解释了所有内容,但至少我可以通过来回更改代码来重现并修复问题.

  • 你是一个救星.一直在努力与这一个两个小时.非常感谢你.人们,注意实体树(我必须编写groupToRemove.getParent().getSubgroups().remove(groupToRemove),并且必须使用cascade = CascadeType.MERGE映射父级).干杯 (2认同)