什麼是hibernate session刷出(flush)?也許大家對此不夠了解,但相信你看完本文一定有很大的收益。
每間隔一段時間,session會執行一些必需的sql語句來把記憶體中的對象的狀态同步到jdbc連接配接中。這個過程被稱為hibernate session刷出(flush)。
預設會在下面的時間點執行:
◆在某些查詢執行之前
◆在調用org.hibernate.transaction.commit()的時候
◆在調用session.flush()的時候
◆涉及的sql語句會按照下面的順序發出執行:
◆所有對實體進行插入的語句,其順序按照對象執行session.save()的時間順序
◆所有對實體進行更新的語句
◆所有進行集合删除的語句
◆所有對集合元素進行删除,更新或者插入的語句
◆所有進行集合插入的語句
◆所有對實體進行删除的語句,其順序按照對象執行session.delete()的時間順序
(有一個例外是,如果對象使用native方式來生成id(持久化辨別)的話,它們一執行save就會被插入。)
除非你明确地發出了flush()指令,關于session何時會執行這些jdbc調用是完全無法保證的,隻能保證它們執行的前後順序。 當然,hibernate保證,query.list(..)絕對不會傳回已經失效的資料,也不會傳回錯誤資料。
也可以改變預設的設定,來讓hibernate session刷出(flush)操作發生的不那麼頻繁。 flushmode類定義了三種不同的方式。僅在送出時刷出(僅當hibernate的transaction api被使用時有效), 按照剛才說的方式刷出,以及除非明确使用flush()否則從不刷出。最後一種模式對于那些需要長時間保持session為打開或者斷線狀态的長時間運作的工作單元很有用。
sess = sf.opensession();
transaction tx = sess.begintransaction();
// allow queries to return stale state
sess.setflushmode(flushmode.commit);
cat izi = (cat) sess.load(cat.class, id);
izi.setname(iznizi);
// might return stale data
sess.find("from cat as cat left outer join cat.kittens kitten");
// change to izi is not flushed!
tx.commit(); // flush occurs
sess.close();
hibernate session刷出(flush)期間,可能會抛出異常。(例如一個dml操作違反了限制)異常處理涉及到對hibernate事務性行為的了解,這裡在事務和并發中有具體的介紹,這裡我們就不加以介紹了。
還有一種情況很值得我們注意——插入大量資料的時候
例如,我現在要插入10000個user,咋辦?
很多人會想這樣:
transaction tx = session.begintransaction();
for(int i=0;i<10000;i++)
{
user u = new user(......);
session.save(u);
}
tx.commit();
session.close();
但随着程式的運作,總會在某一個時間點失敗。并且抛出outofmemoryexception(記憶體溢出)異常!
這是因為hibernate的session持有一個必選的一級緩存,所有的user執行個體都将在session級别的緩存區進行緩存。但緩存區“裝不下了”。
那麼如何解決?
解決方案:定時将session的緩存刷入資料庫!
for(i ==0)
{
session.flush();
session.close();
}