Hibernate 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。
session.flush()的作用是將資料庫與快取中的資料同步
當session.clear()後才會引起快取資料變化,這裡大家要搞清楚。