2014-03-13 44 views
2

我有兩種實體:事件和計劃。我試圖修改它們儘可能避免事務不鎖定數據庫的不必要的時間。休眠:實體副本[事件#XXX]已被分配給不同的實體[事件#XXX]

所以不是:

@Transactional 
public void modify() { 
    Event event = em.find(...); 
    //... something that might take a long time 
    event.addSchedule(schedule); 
    em.flush(); 
} 

我想寧可:

public void modify() { 
    Event event = em.find(...); 
    //... something that might take a long time 
    event.addSchedule(schedule); 
    repository.merge(event); 
} 

... 
@Transactional 
public void merge(Event event) { 
    em.merge(event); 
    em.flush(); 
} 

的問題是這樣的,我得到異常:An entity copy [Event#XXX] was already assigned to a different entity [Event#XXX]。我不會複製實體,也不會做任何意想不到的事情。

另外,據說有必要正確實施equals()和hashCode()方法。我有他們,但我研究的堆棧跟蹤,似乎實體相比,沒有平等的,也不是的hashCode,它們與==比較如下圖所示:http://grepcode.com/file/repo1.maven.org/maven2/org.hibernate/hibernate-core/4.1.3.Final/org/hibernate/event/internal/EventCache.java#62

他們使用IdentityHashMap,具體使用==

那麼我在哪裏可以找到問題?我已經嘗試從4.1.7休眠到目前的4.3.4,並且我使用hibernate.enable_lazy_load_no_trans來加載實體而不顯式地進行會話。

回答

0

似乎有在平等的執行/問題的Event哈希碼:

實體拷貝[事件#1000]已分配給不同的實體[事件#1001]

實體副本是內存中的Java對象,它對應於數據庫中的實體。內存中可能有多個副本指向相同的數據庫記錄。

該消息說,有兩個Event對象具有不同的數據庫標識符(該@Id列),所以從數據庫標識(obj1.getId().equals(obj2.getId()))的點並不相同。

但是從Java等價(obj1.equals(obj2))的角度來看,它們被認爲是相同的。但是兩個對象在數據庫和內存中不可能不同,導致錯誤。

解決方案是修復equals/hashcode實現,有關該問題的更多詳細信息,請參閱此answer,有關實現Hibernate實體的equals/hascode的詳細信息,請參見此page

2

我已經設法解決了這個問題,通過改變Cascade類型從All來持續發佈Class的所有關係。

+0

謝謝。現在已經有一段時間了 – Martin