Hibernate的session中的flush
什麼是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(int i=0;i<10000;i++)
{
User u = new User(......);
session.save(u);
for(i ==0)
{
session.flush();
session.close();
}
}
tx.commit();
session.close();
參考地址:https://developer.51cto.com/art/200909/153860.htm
最後更新:2017-04-03 20:19:32