接前面的例子:http://blog.csdn.net/kunshan_shenbin/archive/2008/09/03/2874375.aspx
測試代碼如下:
1.package com.hb3.pack_22;
2.
3.import java.io.IOException;
4.import java.sql.SQLException;
5.import java.util.List;
6. 7.import org.hibernate.Query;
8.import org.hibernate.Session;
9.import org.hibernate.SessionFactory;
10.import org.hibernate.cfg.Configuration;
11. 12.import com.hb3.pack_22.model.User;
13. 14.public class BusinessService {
15. 16. public static void main(String[] args) throws IOException, SQLException {
17.
18. Configuration config = new Configuration().configure();
19. SessionFactory sessionFactory = config.buildSessionFactory();
20. Session session = sessionFactory.openSession();
21. 22.
23. String hql = "from com.hb3.pack_22.model.User";
24.
25. Query query = session.createQuery(hql);
26. List<?> users = query.list();
27.
28. for(int i = 0; i < users.size(); i++) {
29. User user = (User) users.get(i);
30. System.out.println(user.getName());
31. }
32.
33. query = session.createQuery(hql);
34. users = query.list();
35.
36. for(int i = 0; i < users.size(); i++) {
37. User user = (User) users.get(i);
38. System.out.println(user.getName());
39. }
40. 41. 42. session.close();
43. sessionFactory.close();
44. }
45.}
執行的結果為:
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. 8. <session-factory>
9. ....
10. 11. <property name="hibernate.cache.use_query_cache">true</property>
12. ....
13.
14. </session-factory>
15. 16.</hibernate-configuration>
然後在每次簡歷Query時,執行setCacheable(true):
1.package com.hb3.pack_22;
2.
3.import java.io.IOException;
4.import java.sql.SQLException;
5.import java.util.List;
6. 7.import org.hibernate.Query;
8.import org.hibernate.Session;
9.import org.hibernate.SessionFactory;
10.import org.hibernate.cfg.Configuration;
11. 12.import com.hb3.pack_22.model.User;
13. 14.public class BusinessService {
15. 16. public static void main(String[] args) throws IOException, SQLException {
17.
18. Configuration config = new Configuration().configure();
19. SessionFactory sessionFactory = config.buildSessionFactory();
20. Session session = sessionFactory.openSession();
21. 22.
23. String hql = "from com.hb3.pack_22.model.User";
24.
25. Query query = session.createQuery(hql);
26. //使用Query快取 27. query.setCacheable(true);
28. List<?> 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.
35. query = session.createQuery(hql);
36. //使用Query快取 37. query.setCacheable(true);
38. users = query.list();
39.
40. for(int i = 0; i < users.size(); i++) {
41. User user = (User) users.get(i);
42. System.out.println(user.getName());
43. }
44. 45. 46. session.close();
47. sessionFactory.close();
48. }
49.}
執行結果為:
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.7.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.
3.Query query = session.createQuery("from User");
4.Iterator users = query.iterate();
5.users = query.iterate();
6.
7.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.
3.import java.io.IOException;
4.import java.sql.SQLException;
5.import java.util.Iterator;
6.import java.util.List;
7. 8.import org.hibernate.Query;
9.import org.hibernate.Session;
10.import org.hibernate.SessionFactory;
11.import org.hibernate.cfg.Configuration;
12. 13.import com.hb3.pack_22.model.User;
14. 15.public class BusinessService {
16. 17. public static void main(String[] args) throws IOException, SQLException {
18.
19. Configuration config = new Configuration().configure();
20. SessionFactory sessionFactory = config.buildSessionFactory();
21. Session session = sessionFactory.openSession();
22. 23.
24. String hql = "from com.hb3.pack_22.model.User";
25.
26. Query query = session.createQuery(hql);
27.
28.// List<?> list = query.list(); 29.// Iterator<?> iterator = list.iterator(); 30.// while (iterator.hasNext()) { 31.// User user = (User)iterator.next(); 32.// System.out.println(user.getRoom().getAddress()); 33.// } 34.// System.out.println("====================================="); 35.// list = query.list(); 36.// iterator = list.iterator(); 37.// while (iterator.hasNext()) { 38.// User user = (User)iterator.next(); 39.// System.out.println(user.getRoom().getAddress()); 40.// } 41.//
42.// System.out.println("++++++++++++++++++++++++++++++++++++++"); 43.
44. query = session.createQuery(hql);
45. Iterator<?> iterator = query.iterate();
46. while (iterator.hasNext()) {
47. User user = (User)iterator.next();
48. System.out.println(user.getName());
49. }
50. System.out.println("=====================================");
51. iterator = query.iterate();
52. while (iterator.hasNext()) {
53. User user = (User)iterator.next();
54. System.out.println(user.getName());
55. }
56.
57. session.close();
58. sessionFactory.close();
59. }
60.}
執行結果:
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.
3.import java.io.IOException;
4.import java.sql.SQLException;
5.import java.util.Iterator;
6.import java.util.List;
7. 8.import org.hibernate.Query;
9.import org.hibernate.Session;
10.import org.hibernate.SessionFactory;
11.import org.hibernate.cfg.Configuration;
12. 13.import com.hb3.pack_22.model.User;
14. 15.public class BusinessService {
16. 17. public static void main(String[] args) throws IOException, SQLException {
18.
19. Configuration config = new Configuration().configure();
20. SessionFactory sessionFactory = config.buildSessionFactory();
21. Session session = sessionFactory.openSession();
22. 23.
24. String hql = "from com.hb3.pack_22.model.User";
25.
26. Query query = session.createQuery(hql);
27.
28. List<?> list = query.list();
29. Iterator<?> iterator = list.iterator();
30. while (iterator.hasNext()) {
31. User user = (User)iterator.next();
32. System.out.println(user.getRoom().getAddress());
33. }
34.// System.out.println("====================================="); 35.// list = query.list(); 36.// iterator = list.iterator();
37.// while (iterator.hasNext()) { 38.// User user = (User)iterator.next(); 39.// System.out.println(user.getRoom().getAddress()); 40.// }
41.// 42.// System.out.println("++++++++++++++++++++++++++++++++++++++"); 43.
44. query = session.createQuery(hql);
45.// Iterator<?> iterator = query.iterate(); 46.// while (iterator.hasNext()) { 47.// User user = (User)iterator.next();
48.// System.out.println(user.getName()); 49.// } 50. System.out.println("=====================================");
51. iterator = query.iterate();
52. while (iterator.hasNext()) {
53. User user = (User)iterator.next();
54. System.out.println(user.getName());
55. }
56.
57. session.close();
58. sessionFactory.close();
59. }
60.}
執行的結果為:
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會大大提高性能。