删除不自行引用实体的级联

时间:2010-06-09 05:31:32

标签: java hibernate recursion cascading-deletes

我有以下(简化的)Hibernate实体:

@Entity
@Table(name = "package")
public class Package {
    protected Content content;

    @OneToOne(cascade = {javax.persistence.CascadeType.ALL})
    @JoinColumn(name = "content_id")
    @Fetch(value = FetchMode.JOIN)
    public Content getContent() {
        return content;
    }

    public void setContent(Content content) {
        this.content = content;
    }

}


@Entity
@Table(name = "content")
public class Content {
    private Set<Content> subContents = new HashSet<Content>();
    private ArchivalInformationPackage parentPackage;

    @OneToMany(fetch = FetchType.EAGER)
    @JoinTable(name = "subcontents", joinColumns = {@JoinColumn(name = "content_id")}, inverseJoinColumns = {@JoinColumn(name = "elt")})
    @Cascade(value = {org.hibernate.annotations.CascadeType.DELETE, org.hibernate.annotations.CascadeType.REPLICATE})
    @Fetch(value = FetchMode.SUBSELECT)
    public Set<Content> getSubContents() {
        return subContents;
    }

    public void setSubContents(Set<Content> subContents) {
        this.subContents = subContents;
    }

    @ManyToOne(cascade = {CascadeType.ALL})
    @JoinColumn(name = "parent_package_id")
    public Package getParentPackage() {
        return parentPackage;
    }

    public void setParentPackage(Package parentPackage) {
        this.parentPackage = parentPackage;
    }

}

所以有一个包,其中有一个“顶级”内容。顶级内容链接回包,级联设置为ALL。顶部内容可以具有许多“子”内容,并且每个子内容可以具有其自己的许多子内容。每个子内容都有一个父包,它可能与顶级内容相同也可能不是相同的包(即内容到包的多对一关系)。

关系必须是ManyToOne(包到内容)和ManyToMany(内容到子内容),但对于我目前正在测试每个子内容的情况,只涉及一个包或内容。

问题是,当我删除一个包并刷新会话时,我收到一个Hibernate错误,指出我违反了表subcontents上的外键约束,并且仍然引用了特定的content_id来自表subcontents

我在删除包之前已经特意(递归地)删除了内容,但是我得到了同样的错误。

是否有理由不正确删除此实体树?

编辑:在阅读答案/评论后,我意识到内容不能有多个包,子内容不能有多个父内容,所以我修改了ManyToOne和ManyToMany的注释OneToOne和OneToMany。不幸的是,这并没有解决问题。

我还将内容中的双向链接添加回了我从简化代码中遗漏的父包。

2 个答案:

答案 0 :(得分:1)

如果我理解正确,基于ManyToOne映射,一个内容有很多包,我假设您在上面的简化代码中从Content类中删除了“packages”集合字段?

那么,对于你的“包”收集字段,你是否有一个级联删除(就像你在你的子内容上有的那样)?如果你这样做,那么我认为它应该有效。当您删除根内容时,它应该对每个子内容执行级联删除,然后每个内容将在包上执行级联删除。

这有用吗?

答案 1 :(得分:0)

问题原因是由于我在删除每个包后刷新并清除会话这一事实,并且由于模型中的循环依赖性而不是所有内容都被删除。需要刷新和清除,因为涉及非常大的数据集。最后我更改了它,以便构造一组依赖于当前Package的所有实体(可能包括其他包),然后在调用flush和clear之前删除所有实体。