1. 程式人生 > >hibernate 的evict 和clear

hibernate 的evict 和clear

添加 當前 會話 線程 解決辦法 例子 ict hibernate ida

摘自百度知道:http://zhidao.baidu.com/question/63663640.html

問:
先創建一個Student,然後調用session.save方法,然後再調用evict方法把Student對象清除出緩存,再提交事務, 
可是會報錯:Exception in thread "main" org.hibernate.AssertionFailure: possible nonthreadsafe access to session 
但是如果我用的不是evict方法,而是clear方法用來清除緩存的話,程序沒有錯。 

答:
session.evict(obj),會把指定的緩沖對象進行清除
session.clear(),把緩沖區內的全部對象清除,但不包括操作中的對象

所以,hibernate執行的順序如下,

(1)生成一個事務的對象,並標記當前的Session處於事務狀態(註:此時並未啟動數據庫級事務)。 
(2)應用使用s.save保存對象,這個時候Session將這個對象放入entityEntries,用來標記對象已經
和當前的會話建立了關聯,由於應用對對象做了保存的操作,Session還要在insertions中登記應用
的這個插入行為(行為包括:對象引用、對象id、Session、持久化處理類)。
(3)s.evict將對象從s會話中拆離,這時s會從entityEntries中將這個對象移出。
(4)事務提交,需要將所有緩存flush入數據庫,Session啟動一個事務,並按照insert,update,……,
delete的順序提交所有之前登記的操作(註意:所有insert執行完畢後才會執行update,這裏的特殊
處理也可能會將你的程序搞得一團糟,如需要控制操作的執行順序,要善於使用flush),現在對象不
在entityEntries中,但在執行insert的行為時只需要訪問insertions就足夠了,所以此時不會有任何
的異常。異常出現在插入後通知Session該對象已經插入完畢這個步驟上,這個步驟中需要將entityEntries
中對象的existsInDatabase標誌置為true,由於對象並不存在於entityEntries中,此時Hibernate就
認為insertions和entityEntries可能因為線程安全的問題產生了不同步(也不知道Hibernate的開發者
是否考慮到例子中的處理方式,如果沒有的話,這也許算是一個bug吧),於是一個net.sf.hibernate.AssertionFailure
就被拋出,程序終止

一般錯誤的認為s.save會立即的執行,而將對象過早的與Session拆離,造成了Session的insertions
和entityEntries中內容的不同步。所以我們在做此類操作時一定要清楚Hibernate什麽時候會將數據
flush入數據庫,在未flush之前不要將已進行操作的對象從Session上拆離。
解決辦法是在save之後,添加session.flush。

hibernate 的evict 和clear