2016-05-12 26 views
0

我明白,何時發生NonUniqueObjectException並且它爲什麼會發生。hibernate何時從內存中移除分離的對象| NonUniqueObjectException

我在互聯網上看到很多NonUniqueObjectException的例子,每個例子都是一樣的。 對象首先從session1分離,因此session1也關閉並清除,然後具有相同標識符的對象是session2中的update或SaveorUpdate。

代碼片段:

Session session = sessionFactory1.openSession(); 
Transaction tx = session.beginTransaction(); 
Item item = (Item) session.get(Item.class, new Long(1234)); 
tx.commit(); 
session.close(); // end of first session, item is detached 
item.getId();// The database identity is "1234" item.setDescription("my new description"); 
Session session2 = sessionFactory.openSession(); 
Transaction tx2 = session2.beginTransaction(); 
Item item2 = (Item) session2.get(Item.class, new Long(1234)); 
session2.update(item);// Throws NonUniqueObjectException 
tx2.commit(); 
session2.close(); 

我的問題是,即使seesion1是封閉的,爲什麼休眠保持分離對象在會話1雖然沒有管理它。什麼時候從session1中刪除所有對象?

+0

請將您詢問的代碼複製到此問題中,並鏈接到該代碼(即使外部網站發生故障,您的問題仍然可以理解),並且人們不必訪問外部網站來回答您的問題) – meriton

+0

添加代碼片段 – Dave

回答

1

Hibernate並不保持對它的引用分離對象,即分離對象是不屬於任何會話的一部分,他們的垃圾收集不以任何方式阻礙。

NonUniqueObjectException的原因是同一個數據庫行的兩個不同對象已經與同一個會話關聯。這很糟糕,因爲Hibernate會自動檢測會話中對象的更改,並將這些更改寫回數據庫。如果同一行的多個對象在同一個會話中,則應該寫入哪個對象的狀態是不明確的。因爲這會導致很難發現錯誤,所以Hibernate拒絕這種情況。

通常,Hibernate確保給定會話中某行的所有查詢返回相同的對象,所以不會出現這種情況。但是,如果使用通過新會話從不同會話中獲取的對象,它將與新會話關聯,如果新會話已經包含該行的對象,則會失敗。

這就是爲什麼新的EntityManager API不再具有update方法,即將預先存在的對象與會話相關聯,但將merge方法複製到與會話關聯的對象中。

1

明白了,看看這裏:

http://3.bp.blogspot.com/-katvFbmjewU/Tqv4Ble7_QI/AAAAAAAAAJE/odH15Qm9-hs/s1600/object-states.JPG

Item item2 = (Item) session2.get(Item.class, new Long(1234)); 

這將輪流在持續狀態item2 ID爲1234的session2

session2.update(item); 

item處於分離狀態,update()會變成item的持久狀態上session2 >>>休眠拋出NonUniqueObjectException,因爲有兩個對象Item具有相同的ID在同一會話!

做這樣的:

Session session2 = sessionFactory.openSession(); 
Transaction tx2 = session2.beginTransaction(); 
Item item2 = (Item) session2.get(Item.class, new Long(1234)); 
item2.setDescription("my new description"); 
session2.update(item2); 
tx2.commit(); 
+0

如果我錯了,請更正我的問題,當我執行session1.close()時,它也會調用session1.clear()。因此,如果清除session1,則hibernate不應將對象找到內存中。如果hibernate沒有從內存中刪除對象並且只是斷開會話,那麼上面的行爲是可以理解的。 – Dave

+0

是的,但session2是一個新的會話。 session2不知道'item'對象,因此它會嘗試在數據庫中添加'item',它會失敗...''item'從所有會話中分離,'item2'連接到'session2' – Guillaume

+0

編輯我的回答。 – Guillaume

相關問題