Query 快取


Hibernate的 Session level 快取 會在使用Session的load()方法時起作用,在設定條件進行查詢時,無法使用快取的功能,現在考慮一種情況,您的資料庫表格中的資料很少變動,在 使用Query查詢資料時,如果表格內容沒有變動,您希望能重用上一次查詢的結果,除非表格內容有變動才向資料庫查詢。

您可以開啟Query的快取功能,因為要使用Query的快取功能必須在兩次查詢時所使用的SQL相同,且兩次查詢之間表格沒有任何資料變動下才有意義, 所以Hibernate預設是關閉這個功能的,如果您覺得符合這兩個條件,那麼可以試著開啟Query快取功能來看看效能上有無改進。

先來看看下面的查詢程式片段:
Session session = sessionFactory.openSession();
       
String hql = "from User";
       
Query query = session.createQuery(hql);
List users = query.list();
       
for(int i = 0; i < users.size(); i++) {
    User user = (User) users.get(i);
    System.out.println(user.getName());
}
       
query = session.createQuery(hql);
users = query.list();
       
for(int i = 0; i < users.size(); i++) {
    User user = (User) users.get(i);
    System.out.println(user.getName());
}
       
session.close();

在不啟用Query快取的情況下,Hibernate會使用兩次SQL向資料庫查詢資料:
Hibernate: select user0_.id as id, user0_.name as name0_, user0_.age as age0_ from user user0_
momor
caterpillar
Hibernate: select user0_.id as id, user0_.name as name0_, user0_.age as age0_ from user user0_
momor
caterpillar

如果打算啟用Query快取功能,首先在hibernate.cfg.xml中設定hibernate.cache.use_query_cache屬 性:
  • hibernate.cfg.xml
<?xml version="1.0" encoding="utf-8"?> 
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>

<session-factory>
....

<property name="hibernate.cache.use_query_cache">true</property>
....

</session-factory>

</hibernate-configuration>

然後在每次建立Query實例時,執行setCacheable(true):
Session session = sessionFactory.openSession();
       
String hql = "from User";
       
Query query = session.createQuery(hql);
// 使用Query快取
query.setCacheable(true);
List users = query.list();
       
for(int i = 0; i < users.size(); i++) {
    User user = (User) users.get(i);
    System.out.println(user.getName());
}
       
query = session.createQuery(hql);
// 使用Query快取
query.setCacheable(true);
users = query.list();
       
for(int i = 0; i < users.size(); i++) {
    User user = (User) users.get(i);
    System.out.println(user.getName());
}
       
session.close();

Hibernate在啟用Query快取後,會保留執行過的查詢SQL與查詢結果,在下一次查詢時會看看SQL是否相同,並看看對應的資料庫表格是否有變 動(Update/Delete/Insert),如果SQL相同且資料庫也沒有變動,則將Query快取中的查詢結果返回,上面的程式片段將使用一次 SQL查詢,第二次查詢時直接返回快取中的結果:
Hibernate: select user0_.id as id, user0_.name as name0_, user0_.age as age0_ from user user0_
momor
caterpillar
momor
caterpillar