Hibernate Gossip: 簡介快取(Session Level)

Hibernate Gossip: 簡介快取(Session Level)

資料庫每一次的查詢都是一次不小的開銷,例如連結的開啟、執行查詢指令,當資料庫與應用伺服器不在同一個伺服器上時,還必須有遠程調用、Socket的建立等開銷,在Hibernate這樣的ORM框架中,還有資料的封裝等開銷必須考慮進去。

快取(Cache)是資料庫在記憶體中的臨時容器,從資料庫中讀取的資料在快取中會有一份臨時拷貝,當您查詢某個數據時,會先在快取中尋找是否有相對應的拷貝,如果有的話就直接返回資料,而無需連接資料庫進行查詢,只有在快取中找不到資料時,才從資料庫中查詢資料,藉由快取,可以提昇應用程式讀取資料時的效能。

對於Hibernate這樣的ORM框架來說,快取的機制更形重要,在Hibernate中快取分作兩個層級:Session level與SessionFactory level(又稱Second level快取)。

這邊先介紹Session level的快取,在Hibernate中Session level快取會在使用主鍵載入資料或是延遲初始(Lazy Initialization) 時作用,Session level的快取隨著Session建立時建立,而Session銷毀時銷毀。

Session會維護一個Map容器,並保留與目前Session發生關係的資料,當您透過主鍵來載入資料時,Session會先依據所要載入的類別與所給定的主鍵,看看Map中是否已有資料,如果有的話就返回,若沒有就對資料庫進行查詢,並在載入資料後在Map中維護。

可以透過==來比較兩個名稱是否參考至同一個物件,以檢驗這個事實:
Session session = sessionFactory.openSession();
User user1 = (User) session.load(User.class, new Integer(1));
User user2 = (User) session.load(User.class, new Integer(1));
System.out.println(user1 == user2);
session.close();

第二次查詢資料時,由於在快取中找到資料物件,於是直接返回,這與第一次查詢到的資料物件是同一個實例,所以會顯示true的結果。

可以透過evict()將某個物件從快取中移去,例如:
Session session = sessionFactory.openSession();
User user1 = (User) session.load(User.class, new Integer(1));
session.evict(user1);
User user2 = (User) session.load(User.class, new Integer(1));
System.out.println(user1 == user2);
session.close();

由於user1所參考的物件被從快取中移去了,在下一次查詢時,Session在Map容器中找不到對應的資料,於是重新查詢資料庫並再封裝一個物件,所以user1與user2參考的是不同的物件,結果會顯示false。

也可以使用clear()清除快取中的所有物件,例如:
Session session = sessionFactory.openSession();
User user1 = (User) session.load(User.class, new Integer(1));
session.clear();
User user2 = (User) session.load(User.class, new Integer(1));
System.out.println(user1 == user2);
session.close();

同樣的道理,這次也會顯示false。

Session level的快取隨著Session建立與銷毀,看看下面這個程式片段:
Session session1 = sessionFactory.openSession();
User user1 = (User) session1.load(User.class, new new Integer(1));
session1.close();

Session session2 = sessionFactory.openSession();
User user2 = (User)session2.load(User.class, new Integer(1));
session2.close();

System.out.println(user1 == user2);

第一個Session在關閉後,快取也關閉了,在第二個Session的查詢中並無法用到第一個Session的快取,兩個Session階段所查詢到的並不是同一個物件,結果會顯示false。

在載入大量資料時,Session level 快取的內容會太多,記得要自行執行clear()清除快取或是用evict()移去不使用物件,以釋放快取所佔據的資源。

您也可以使用Session的setReadOnly(object, true),設定某物件為唯讀,對於唯讀資料,不會在快取中維護一個複本,不會執行dirty check。


 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值