2012-06-27 21 views
6

我該如何取消一個hibernate對象的處理,以支持多態性?如何取消一個hibernate對象

考慮下面的例子。類A和B是兩個hibernate實體。 B具有兩種亞型C和D.

List<A> resultSet = executeSomeHibernateQuery(); 
for(A nextA : resultSet) { 
    for(B nextB : nextA.getBAssociations() { 
     if(nextB instanceof C) { 
      // do something for C 
     } else if (nextB instanceof D) { 
      // do something for D 
     } 
    } 
} 

此代碼無法執行C或d塊,由於B收集已延遲裝入,和B的所有實例是休眠的代理。我想要一個方法來取消每個實例的代理。

注:我意識到查詢可以優化,以熱切地獲取所有B的。我正在尋找替代品。

+1

我知道這是一個古老的問題,但因爲它出現在谷歌搜索中的第一個結果,我必須在這裏評論,如果你必須使用'instanceof',那麼你可能在做多態錯誤。 – drigoangelo

回答

18

這裏是我們的解決方案,加入到我們的持久utils的:

public T unproxy(T proxied) 
{ 
    T entity = proxied; 
    if (entity instanceof HibernateProxy) { 
     Hibernate.initialize(entity); 
     entity = (T) ((HibernateProxy) entity) 
        .getHibernateLazyInitializer() 
        .getImplementation(); 
    } 
    return entity; 
} 
+0

此解決方案適合您嗎?我已經實現了類似的方法,我仍然有一個'HibernateProxy'作爲我的對象的一個​​類。這是我的問題:http://stackoverflow.com/q/11518091/845220 – woyaru

+0

這不解決'PersistentCollection'的問題。通常你可以有一個'List ',它實際上被代入PersistentCollection。如果通過此方法傳遞,測試HibernateProxy的實體實例將會失敗,並且該方法將返回而不執行任何操作。一個解決方案也是測試'instance instanceof PersistentCollection',同樣使用'Hibernate.initialize()',然後迭代和取消集合的每個對象。更容易描述,但要實現雖然.. – Aldian

+1

請注意,您不需要檢查該實體不爲空(請參閱http://stackoverflow.com/questions/2950319/is-null-check-needed-before-calling -instanceof) – laurent

2

使用HibernateProxy和getImplementationMethod的解決方案是正確的。

但是,我認爲你遇到了這個問題,因爲你的集合被定義爲一個接口,並且hibernate向接口呈現代理。

這導致了設計問題,爲什麼要使用「instanceof」而不是使用接口方法來執行所需的操作。

所以,你的循環就變成了:

for(B nextB : nextA.getBAssociations() { 
    nextB.doSomething(); 
} 

這樣,冬眠將委託調用「DoSomething的()」,以實際執行的對象,你永遠不會知道其中的差別。

+0

好點,我們使用繼承可能不太理想。在這種特殊情況下,我們實際上有其他邏輯取決於集合中每個項目的類型。因此,我們可以做的一件事就是添加isC()和isD()抽象方法,但這也感覺有點笨拙。 FWIW,我們的層次結構適用於大多數用例,這是20%的一部分。 –

相關問題