hibernate中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,由於對象並不存在於entityEntres中,此時Hibernate就認為insertions和entityEntries可能因為線程安全的問題產生了不同步(也不知道Hibernate的開發者是否考慮到例子中的處理方式,如果沒有的話,這也許算是一個bug吧),於是一個net.sf.hibernate.AssertionFailure就被拋出,程序終止。
一般我們會錯誤的認為s.sava會立即執行,而將對象過早的與session拆離,造成了session的insertion和entityEntries中內容的不同步。所以我們在做此類操作時一定要清楚hibernate什麽時候會將數據flush入數據庫,在未flush之前不要將已進行操作的對象從session上拆離,解決辦法是在sava之後,添加session.flush。
hibernate中evict()和clear()的區別