測試代碼如下:

  1. package com.hb3.pack_22;

  2. import java.io.IOException;
  3. import java.sql.SQLException;
  4. import java.util.List;

  5. import org.hibernate.Query;
  6. import org.hibernate.Session;
  7. import org.hibernate.SessionFactory;
  8. import org.hibernate.cfg.Configuration;

  9. import com.hb3.pack_22.model.User;

  10. public class BusinessService {

  11.     public static void main(String[] args) throws IOException, SQLException {
  12.         
  13.         Configuration config = new Configuration().configure();
  14.         SessionFactory sessionFactory = config.buildSessionFactory();      
  15.         Session session = sessionFactory.openSession();

  16.         
  17.         String hql = "from com.hb3.pack_22.model.User";
  18.         
  19.         Query query = session.createQuery(hql);
  20.         List<?> users = query.list();
  21.                 
  22.         for(int i = 0; i < users.size(); i++) {
  23.             User user = (User) users.get(i);
  24.             System.out.println(user.getName());
  25.         }
  26.                 
  27.         query = session.createQuery(hql);
  28.         users = query.list();
  29.                 
  30.         for(int i = 0; i < users.size(); i++) {
  31.             User user = (User) users.get(i);
  32.             System.out.println(user.getName());
  33.         }


  34.         session.close();
  35.         sessionFactory.close();
  36.     }
  37. }

執行的結果為:

Hibernate: select user0_.id as id0_, user0_.name as name0_, user0_.room_id as room3_0_ from user user0_
chenyan
shenbin
Hibernate: select user0_.id as id0_, user0_.name as name0_, user0_.room_id as room3_0_ from user user0_
chenyan
shenbin

 

可見,沒有啟用Query的快取功能。

如果打算打開Query的快取功能,首先在hibernate.cfg.xml中設定hibernate.cache.use_query_cache屬性:

  1. <?xml version="1.0" encoding="utf-8"?> 
  2. <!DOCTYPE hibernate-configuration PUBLIC
  3.     "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
  4.     "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
  5.     
  6. <hibernate-configuration> 

  7.     <session-factory> 
  8.         .... 

  9.         <property name="hibernate.cache.use_query_cache">true</property> 
  10.         ....
  11.         
  12.     </session-factory> 

  13. </hibernate-configuration>

然后在每次簡歷Query時,執行setCacheable(true):

  1. package com.hb3.pack_22;

  2. import java.io.IOException;
  3. import java.sql.SQLException;
  4. import java.util.List;

  5. import org.hibernate.Query;
  6. import org.hibernate.Session;
  7. import org.hibernate.SessionFactory;
  8. import org.hibernate.cfg.Configuration;

  9. import com.hb3.pack_22.model.User;

  10. public class BusinessService {

  11.     public static void main(String[] args) throws IOException, SQLException {
  12.         
  13.         Configuration config = new Configuration().configure();
  14.         SessionFactory sessionFactory = config.buildSessionFactory();      
  15.         Session session = sessionFactory.openSession();

  16.         
  17.         String hql = "from com.hb3.pack_22.model.User";
  18.         
  19.         Query query = session.createQuery(hql);
  20.         //使用Query快取
  21.         query.setCacheable(true);
  22.         List<?> users = query.list();
  23.                 
  24.         for(int i = 0; i < users.size(); i++) {
  25.             User user = (User) users.get(i);
  26.             System.out.println(user.getName());
  27.         }
  28.                 
  29.         query = session.createQuery(hql);
  30.         //使用Query快取
  31.         query.setCacheable(true);
  32.         users = query.list();
  33.                 
  34.         for(int i = 0; i < users.size(); i++) {
  35.             User user = (User) users.get(i);
  36.             System.out.println(user.getName());
  37.         }


  38.         session.close();
  39.         sessionFactory.close();
  40.     }
  41. }

執行結果為:

Hibernate: select user0_.id as id0_, user0_.name as name0_, user0_.room_id as room3_0_ from user user0_
chenyan
shenbin
chenyan
shenbin

 

其實,Hibernate在啟用Query的緩存機制后,會保留執行過的查詢SQL和查詢結果,在下次查詢后會看看SQL是否相同,并看看對應的資 料庫表格是否有變動(Update/Delete/Insert),如果SQL相同且且資料庫也沒有變動則將緩存中的結果直接返回。

 

值得一提的是,Query上有list()與iterator()2個方法用于結果集返回。他們的區別是,list()方法在讀取數據庫時不會使用緩存機制而直接向數據庫發起查詢,而iterator()則會將讀取到的結果寫到緩存中,以便于讀取時再次利用。

  1. Session session = sessionFactory.openSession();
  2.         
  3. Query query = session.createQuery("from User");
  4. List users = query.list();
  5. users = query.list();

  6. session.close();

執行結果:

Hibernate: select user0_.id as id, user0_.name as name0_, user0_.age as age0_ from user user0_
Hibernate: select user0_.id as id, user0_.name as name0_, user0_.age as age0_ from user user0_

  1. Session session = sessionFactory.openSession();

  2. Query query = session.createQuery("from User");
  3. Iterator users = query.iterate();
  4. users = query.iterate();

  5. session.close();

執行結果:

Hibernate: select user0_.id as col_0_0_ from user user0_

Hibernate: select user0_.id as col_0_0_ from user user0_

 

由于使用iterator()方法時會使用到Session level緩存,所以在查詢大量記錄時會好用大量的記憶體。必要時可以使用Session的evict()或clear()方法來清除緩存。

請參閱:http://blogger.org.cn/blog/more.asp?name=NaddyLee&id=31540

請注意,盡管iterator()方法時會使用到Session level緩存,但這不能就說在任何情況下都是最有效率的做法。

請看下面的測試:

  1. package com.hb3.pack_22;

  2. import java.io.IOException;
  3. import java.sql.SQLException;
  4. import java.util.Iterator;
  5. import java.util.List;

  6. import org.hibernate.Query;
  7. import org.hibernate.Session;
  8. import org.hibernate.SessionFactory;
  9. import org.hibernate.cfg.Configuration;

  10. import com.hb3.pack_22.model.User;

  11. public class BusinessService {

  12.     public static void main(String[] args) throws IOException, SQLException {
  13.         
  14.         Configuration config = new Configuration().configure();
  15.         SessionFactory sessionFactory = config.buildSessionFactory();      
  16.         Session session = sessionFactory.openSession();

  17.         
  18.         String hql = "from com.hb3.pack_22.model.User";
  19.         
  20.         Query query = session.createQuery(hql);
  21.         
  22. //        List<?> list = query.list();
  23. //        Iterator<?> iterator = list.iterator();
  24. //        while (iterator.hasNext()) {
  25. //          User user = (User)iterator.next();
  26. //          System.out.println(user.getRoom().getAddress());
  27. //      }
  28. //        System.out.println("=====================================");
  29. //        list = query.list();
  30. //        iterator = list.iterator();
  31. //        while (iterator.hasNext()) {
  32. //          User user = (User)iterator.next();
  33. //          System.out.println(user.getRoom().getAddress());
  34. //      }
  35. //        
  36. //        System.out.println("++++++++++++++++++++++++++++++++++++++");
  37.         
  38.         query = session.createQuery(hql);
  39.         Iterator<?> iterator = query.iterate();
  40.         while (iterator.hasNext()) {
  41.             User user = (User)iterator.next();
  42.             System.out.println(user.getName());
  43.         }
  44.         System.out.println("=====================================");
  45.         iterator = query.iterate();
  46.         while (iterator.hasNext()) {
  47.             User user = (User)iterator.next();
  48.             System.out.println(user.getName());
  49.         }
  50.         
  51.         session.close();
  52.         sessionFactory.close();
  53.     }
  54. }

執行結果:

Hibernate: select user0_.id as col_0_0_ from user user0_
Hibernate: select user0_.id as id0_1_, user0_.name as name0_1_, user0_.room_id as room3_0_1_, room1_.id as id1_0_, room1_.address as address1_0_ from user user0_ left outer join room room1_ on user0_.room_id=room1_.id where user0_.id=?
chenyan
Hibernate: select user0_.id as id0_1_, user0_.name as name0_1_, user0_.room_id as room3_0_1_, room1_.id as id1_0_, room1_.address as address1_0_ from user user0_ left outer join room room1_ on user0_.room_id=room1_.id where user0_.id=?
shenbin
=====================================
Hibernate: select user0_.id as col_0_0_ from user user0_
chenyan
shenbin

看見,Iterator中的元素并不是一次性返回的,而是一條一條返回的。當數據量龐大時,特性就會下降。

再看下面的測試代碼:

  1. package com.hb3.pack_22;

  2. import java.io.IOException;
  3. import java.sql.SQLException;
  4. import java.util.Iterator;
  5. import java.util.List;

  6. import org.hibernate.Query;
  7. import org.hibernate.Session;
  8. import org.hibernate.SessionFactory;
  9. import org.hibernate.cfg.Configuration;

  10. import com.hb3.pack_22.model.User;

  11. public class BusinessService {

  12.     public static void main(String[] args) throws IOException, SQLException {
  13.         
  14.         Configuration config = new Configuration().configure();
  15.         SessionFactory sessionFactory = config.buildSessionFactory();      
  16.         Session session = sessionFactory.openSession();

  17.         
  18.         String hql = "from com.hb3.pack_22.model.User";
  19.         
  20.         Query query = session.createQuery(hql);
  21.         
  22.         List<?> list = query.list();
  23.         Iterator<?> iterator = list.iterator();
  24.         while (iterator.hasNext()) {
  25.             User user = (User)iterator.next();
  26.             System.out.println(user.getRoom().getAddress());
  27.         }
  28. //        System.out.println("=====================================");
  29. //        list = query.list();
  30. //        iterator = list.iterator();
  31. //        while (iterator.hasNext()) {
  32. //          User user = (User)iterator.next();
  33. //          System.out.println(user.getRoom().getAddress());
  34. //      }
  35. //        
  36. //        System.out.println("++++++++++++++++++++++++++++++++++++++");
  37.         
  38.         query = session.createQuery(hql);
  39. //        Iterator<?> iterator = query.iterate();
  40. //        while (iterator.hasNext()) {
  41. //          User user = (User)iterator.next();
  42. //          System.out.println(user.getName());
  43. //      }
  44.         System.out.println("=====================================");
  45.         iterator = query.iterate();
  46.         while (iterator.hasNext()) {
  47.             User user = (User)iterator.next();
  48.             System.out.println(user.getName());
  49.         }
  50.         
  51.         session.close();
  52.         sessionFactory.close();
  53.     }
  54. }

執行的結果為:

Hibernate: select user0_.id as id0_, user0_.name as name0_, user0_.room_id as room3_0_ from user user0_
Hibernate: select room0_.id as id1_0_, room0_.address as address1_0_ from room room0_ where room0_.id=?
NTU-M8-419
NTU-M8-419
=====================================
Hibernate: select user0_.id as col_0_0_ from user user0_
chenyan
shenbin

 

這明顯在性能上要優于剛才的做法。可見,首次查詢使用query.list性能要優于query.iterate,之后再做相同的查詢請求時,則借助緩存機制,使用query.iterate會大大提高性能。



ExtJS教程- Hibernate教程-Struts2 教程-Lucene教程