2010-06-09 104 views
0

我有以下的(簡化)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仍引用。

我已經試過(遞歸)刪除包之前刪除內容,但我得到同樣的錯誤。

是否有這個實體樹沒有被正確刪除的原因?

編輯:閱讀答案後/評論我認識到,一個內容不能有多個包,和子內容不能有多個父目錄,所以我已經修改從多對一和多對多的註解OneToOne和一對多。不幸的是,這並沒有解決問題。

我也添加了雙向鏈接,從內容返回到父程序包,我省略了簡化代碼。

+1

包和內容之間的雙向關係(代碼沒有顯示,但在閱讀描述後我有疑問)? – 2010-06-09 20:38:24

+0

是的,這種關係是雙向的,我不應該從簡化的代碼中解脫出來。 – jwaddell 2010-06-10 02:11:00

+0

嗯...... Package和Content之間的基數仍然是不一致的:)是OneToOne還是OneToMany(你現在有一個ManyToOne從Content到Package)? – 2010-06-10 02:24:27

回答

0

問題原來是由於在刪除每個包後我正在刷新和清除會話,並且由於模型中的循環依賴關係而不是所有內容都被刪除。因爲涉及非常大的數據集,所以需要刷新和清除。最後,我改變了它,以便構建一組依賴於當前包的所有實體(可能包含其他包),然後在調用flush和clear之前全部刪除。

1

如果我理解正確,基於ManyToOne映射,一個內容有很多包,並且我假設你在上面的簡化代碼中從Content類中刪除了「包」集合字段?

因此,對於您的「軟件包」收集字段,您是否具有級聯刪除(就像您對子包含的內容)?如果你這樣做,那麼我認爲它應該工作。刪除根內容時,應對每個子內容執行級聯刪除,然後每個內容將對包進行級聯刪除。

這是否行得通?

+0

閱讀完本文之後,我給了它更多思考,並意識到它確實不應該是ManyToOne關係,所以我將它修改爲OneToOne。我仍然得到同樣的錯誤,我猜這是有道理的,因爲數據庫中沒有反映ManyToOne關係的數據。 我已經更新了Package和Content之間關係的摘要。 所以它是OneToOne for Package到「top」Content,但ManyToOne for Content返回到Package(因爲top和sub內容可能共享相同的包)。這種差異會導致問題嗎? – jwaddell 2010-06-10 02:31:02