2009-02-14 90 views
10

從列表中刪除項目時遇到問題。該列表在超類中定義,但Hibernate註釋應用於子類中的屬性訪問器。超類中有兩種方法可以操縱列表。 「添加」方法工作正常,但「刪除」不會持續更改。我檢查了我的Cascade設置,並且我似乎有些事情是正確的。我在做一些不可能的事情嗎?如果不是,我是否做了不正確的事情?休眠:從列表中刪除項目不會持續

這裏是我的課:

@Entity 
abstract class Temporal<T> { 
    @Id 
    @GeneratedValue 
    private Long id; 

    @Version 
    private Integer version = null; 

    @Transient 
    protected List<T> content = new ArrayList<T>(); 

    public void remove(T value) { 
     // business logic ... 
     content.remove(value); 
    } 

    public void add(T value) { 
     // business logic ... 
     content.add(value); 
    } 
} 

@Entity 
@AccessType("property") 
class TemporalAsset extends Temporal<Asset> { 
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "temporal") 
    public List<Asset> getContent() { 
     return super.content; 
    } 

    protected void setContent(List<Asset> list) { 
     super.content = list; 
    } 
} 

我使用TemporalAsset類的一個實例如下(注意,我只使用「刷新」的方法來證明行爲列表不正確地堅持,即使如果我刷新或關閉會話並打開新會話):

temporalAsset.add(value1); 
temporalAsset.getContent().size() == 1; // true 
session.update(temporalAsset); 

session.refresh(temporalAsset); 

temporalAsset.getContent().size() == 1; // true 

temporalAsset.remove(value1); 
temporalAsset.getContent().size() == 0; // true 
session.update(temporalAsset); 

session.refresh(temporalAsset); 

temporalAsset.getContent().size() == 0; // false, its 1 

謝謝。

回答

14

你必須明確地指定級聯爲CascadeType.DELETE_ORPHAN。

嘗試從休眠docs更改代碼

@OneToMany  
@Cascade(cascade = {CascadeType.ALL, CascadeType.DELETE_ORPHAN}, mappedBy = "temporal") 

部分:

如果子對象的壽命是由父 對象的壽命限定 ,讓家長全 生命週期對象通過指定 CascadeType.ALL和 org.hibernate.annotations.CascadeType。DELETE_ORPHAN (請參閱Hibernate 參考指南 孤兒的語義刪除)

+0

就是這樣!非常感謝 – codefinger 2009-02-15 15:41:50

+0

CascadeType.DELETE_ORPHAN已棄用。有其他選擇嗎? – 2012-03-01 14:27:02

0

嘗試刪除對Session.refresh()的調用。從文檔:

從底層數據庫重新讀取給定的 實例的狀態。 這是不宜使用這 執行長期運行的會話, 跨越許多業務任務。然而,這種方法 在某些特殊的 的情況下是有用的。例如

  • 其中一個數據庫觸發器插入時改變對象狀態或更新
  • 插入BLOB或CLOB
之後執行直接SQL(例如質量更新)在同一會話
  • http://www.hibernate.org/hib_docs/v3/api/org/hibernate/Session.html#refresh(java.lang.Object)

    如果你刷新()之前調用flush(),這可能會解決問題也一樣,因爲沖洗( )確保任何掛起的SQL將針對數據庫執行。在實踐中,我幾乎從來沒有見過任何人使用refresh(),它看起來不像你需要的代碼。

    這從文檔章節是值得一讀:

    http://www.hibernate.org/hib_docs/v3/reference/en/html/objectstate.html

    +0

    我只在這裏包括了刷新來演示行爲。實際上,刷新不會將更改保留在列表中。我甚至可以關閉會話,打開一個新會話,並且該列表仍然具有值。 – codefinger 2009-02-15 00:39:14

    0

    你已經標記「內容」字段作爲超一流的瞬態。我至少會懷疑這是造成問題的原因。通過子類中的映射,現在基本上有兩個相同屬性的相互矛盾的映射。