2009-09-17 175 views
1

我遇到了一個問題,我試圖在Hibernate中進行刪除操作。每次我嘗試刪除時,由於存在子記錄,我得到一個問題,因此無法刪除父項。我想刪除孩子和父母。這裏是我的父映射:休眠級聯刪除不起作用

<set name="communicationCountries" inverse="true" cascade="all,delete-orphan"> 
     <key column="COM_ID" not-null="true" on-delete="cascade" /> 
     <one-to-many class="com.fmr.fc.portlet.communications.vo.CommunicationCountry"/> 
</set> 

這裏是子類的映射:

<many-to-one name="communication" column="COM_ID" not-null="true" class="com.fmr.fc.portlet.communications.vo.Communication" cascade="all"/> 

編輯 - 當我插入的數據插入到家長和孩子。

當我使用一個新的對象的ID與對象的ID進行更新時,我想要修改父級更新,但是第二次添加任何現有的子級。我似乎無法刪除孩子。當我使用ID檢索一個對象並修改它時,我得到一個錯誤告訴我org.hibernate.LazyInitializationException:無法初始化代理 - 擁有的Session被關閉。我懷疑這是因爲在一個getHibernateTemplate()調用中,我得到的對象,我將它保存在另一個,這是兩個不同的會話?

當我做刪除時,我得到一個錯誤,因爲孩子存在。我知道我只是在做一些愚蠢的事情,因爲缺乏對這一切如何運作的線索。

這裏是我的更新和刪除方法,在這種情況下,更新/保存是在保存前檢索和修改。刪除使用新的對象具有相同ID作爲一個在DB我想刪除:

public void deleteCommunication(Communication comm) throws DataAccessException 
{ 
    getHibernateTemplate().delete(comm); 
} 

public void saveCommunication(Communication comm) throws DataAccessException 
{  
    Communication existing = (Communication)getHibernateTemplate().load(Communication.class, comm.getComId()); 
    existing.getCommunicationCountries().clear(); 

    getHibernateTemplate().saveOrUpdate(existing);  
} 

UPDATE 因此,這裏有我的新方法,但仍然沒有喜悅。我認爲我的問題與未加載/初始化等的兒童有關。雖然刪除,但我不明白爲什麼沒有發生級聯刪除。

非常感謝您的幫助。我已經達到了我對這項工作已經截止,所以如果我不把它固定在週末我只是將不得不求助於執行HQL查詢,因爲我知道,會爲我工作:(

public void deleteCommunication(Integer id) throws DataAccessException 
    { 
     HibernateTemplate hibernate = getHibernateTemplate(); 
     Communication existing = (Communication)hibernate.get(Communication.class, id); 
     hibernate.initialize(existing.getCommunicationCountries()); 
     hibernate.delete(existing); 
    } 

    public void updateCommunication(Communication comm) throws DataAccessException 
    {  
     HibernateTemplate hibernate = getHibernateTemplate(); 
     Communication existing = (Communication)hibernate.get(Communication.class, comm.getComId()); 
     hibernate.initialize(existing.getCommunicationCountries()); 
     existing.getCommunicationCountries().clear(); 
     hibernate.saveOrUpdate(existing);  
    } 
+0

你可以添加hibernate映射嗎?你有沒有爲關係指定級聯? – 2009-09-17 15:34:22

+0

'all,delete-orphan'不是級聯標識符。 'all-delete-orphan'是。 – Jherico 2009-09-17 17:54:40

+0

@Jherico - 兩者完全一樣:http://docs.jboss.org/hibernate/stable/core/reference/en/html/collections.html#collections-mapping。 「all」和「delete-orphan」是有效的級聯操作,可以用逗號分隔多個值。 – ChssPly76 2009-09-17 18:23:07

回答

2

在沒有特定的順序:

A)在你的代碼假設「身份識別碼」是你的實體的標識,你應該用session.get(),而不是標準 - 它的速度更快,最肯定更容易:

MyObject obj = (MyObject) session.get(MyObject.class, new Long(1)); 

B)如果您使用的是Spring(通過getHibernateTemplate()調用來判斷),您應該始終如一地使用它:-)而不是直接調用會話,除非絕對必要 - 而且幾乎沒有必要。因此,上述get方法將成爲:

MyObject obj = (MyObject) getHibernateTemplate().get(MyObject.class, new Long(1)); 

如果你需要編寫一個基於標準的查詢,你可以使用DetachedCriteriaHibernateTemplate.getByCriteria()方法:

DetachedCriteria crit = DetachedCriteria.forClass(MyObject.class) 
.add(Property.forName("myId").eq(new Long(1))); 
List results = getHibernateTemplate().findByCriteria(crit); 

C)通常你不應該evict()對象從會議開始(在結束之前立即進行是毫無意義的)。您通常也不應該從HibernateTemplate獲得的會話。

d)最後,至於自動保存孩子(一個一對多的集合元素)去 - 看看this example它提供了不同梯級設置一個很好的解釋。如果你仍然有問題,請發佈你的映射/代碼。

更新(基於問題的澄清):

1)你的映射看起來除了在子類(<many-to-one name="communication" cascade="all"/>)母公司級聯確定。你很可能不想要這個。

2)LazyInitializationException被拋出,因爲默認情況下Hibernate將集合映射爲懶惰,這意味着子項(通訊國家)將不會被加載,直到第一次訪問。如果在會話已關閉時發生訪問,則會引發異常。您可以通過致電Hibernate.initialize()收集來確保集合已填充。 3)你的delete()應該可以很好地工作正如你在Hibernate返回的實體實例上調用它,而不是你自己創建的那個(比如遠程調用解組)的「communicationCountries」集合是沒有填充。爲了讓Hibernate刪除孩子,需要知道他們存在。

4)另一方面,您的更新()是錯誤的。你正在加載一個實體,清除它的子元素,然後再次保存 - 這本身就很好 - 但是沒有連接到傳入的參數。

+0

感謝您的詳細回覆。你也喜歡的例子實際上是我正在使用的例子,但我懷疑我只是不明白髮生了什麼。 所以,如果我想更新一個對象,我可以創建一個具有相同ID的新對象並保存它。當我這樣做時,對象被更新,但如果我原本有兩個孩子,我又添加了一個,我最終有5個,其中2個是重複的。另外,如果我從集合中刪除所有孩子,則在數據庫中都不會刪除任何孩子。 我有同樣的問題刪除父,級聯刪除的孩子沒有發生,所以我得到一個異常。 – Caroline 2009-09-17 21:23:00

+0

在主要問題中增加了更多詳細信息.... – Caroline 2009-09-17 21:47:18

+0

如果您想**更新**一個對象,那麼您肯定無法**創建**具有相同ID的新對象。那麼,你可以在理論上使用'merge()',但我會強烈建議反對它,直到你明確地知道你在做什麼。 – ChssPly76 2009-09-17 21:51:04