接前面的例子:http://blog.csdn.net/kunshan_shenbin/archive/2008/09/03/2874375.aspx
测试代码如下:
- package com.hb3.pack_22;
- import java.io.IOException;
- import java.sql.SQLException;
- import java.util.List;
- import org.hibernate.Query;
- import org.hibernate.Session;
- import org.hibernate.SessionFactory;
- import org.hibernate.cfg.Configuration;
- import com.hb3.pack_22.model.User;
- public class BusinessService {
- public static void main(String[] args) throws IOException, SQLException {
-
- Configuration config = new Configuration().configure();
- SessionFactory sessionFactory = config.buildSessionFactory();
- Session session = sessionFactory.openSession();
-
- String hql = "from com.hb3.pack_22.model.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();
- sessionFactory.close();
- }
- }
执行的结果为:
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属性:
- xml version="1.0" encoding="utf-8"?>
- "-//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">trueproperty>
- ....
-
- session-factory>
- hibernate-configuration>
然后在每次简历Query时,执行setCacheable(true):
- package com.hb3.pack_22;
- import java.io.IOException;
- import java.sql.SQLException;
- import java.util.List;
- import org.hibernate.Query;
- import org.hibernate.Session;
- import org.hibernate.SessionFactory;
- import org.hibernate.cfg.Configuration;
- import com.hb3.pack_22.model.User;
- public class BusinessService {
- public static void main(String[] args) throws IOException, SQLException {
-
- Configuration config = new Configuration().configure();
- SessionFactory sessionFactory = config.buildSessionFactory();
- Session session = sessionFactory.openSession();
-
- String hql = "from com.hb3.pack_22.model.User";
-
- Query query = session.createQuery(hql);
-
- 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.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();
- sessionFactory.close();
- }
- }
执行结果为:
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()则会将读取到的结果写到缓存中,以便于读取时再次利用。
- Session session = sessionFactory.openSession();
-
- Query query = session.createQuery("from User");
- List users = query.list();
- users = query.list();
- 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_
- Session session = sessionFactory.openSession();
- Query query = session.createQuery("from User");
- Iterator users = query.iterate();
- users = query.iterate();
- 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缓存,但这不能就说在任何情况下都是最有效率的做法。
请看下面的测试:
- package com.hb3.pack_22;
- import java.io.IOException;
- import java.sql.SQLException;
- import java.util.Iterator;
- import java.util.List;
- import org.hibernate.Query;
- import org.hibernate.Session;
- import org.hibernate.SessionFactory;
- import org.hibernate.cfg.Configuration;
- import com.hb3.pack_22.model.User;
- public class BusinessService {
- public static void main(String[] args) throws IOException, SQLException {
-
- Configuration config = new Configuration().configure();
- SessionFactory sessionFactory = config.buildSessionFactory();
- Session session = sessionFactory.openSession();
-
- String hql = "from com.hb3.pack_22.model.User";
-
- Query query = session.createQuery(hql);
-
-
- query = session.createQuery(hql);
- Iterator> iterator = query.iterate();
- while (iterator.hasNext()) {
- User user = (User)iterator.next();
- System.out.println(user.getName());
- }
- System.out.println("=====================================");
- iterator = query.iterate();
- while (iterator.hasNext()) {
- User user = (User)iterator.next();
- System.out.println(user.getName());
- }
-
- session.close();
- sessionFactory.close();
- }
- }
执行结果:
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中的元素并不是一次性返回的,而是一条一条返回的。当数据量庞大时,特性就会下降。
再看下面的测试代码:
- package com.hb3.pack_22;
- import java.io.IOException;
- import java.sql.SQLException;
- import java.util.Iterator;
- import java.util.List;
- import org.hibernate.Query;
- import org.hibernate.Session;
- import org.hibernate.SessionFactory;
- import org.hibernate.cfg.Configuration;
- import com.hb3.pack_22.model.User;
- public class BusinessService {
- public static void main(String[] args) throws IOException, SQLException {
-
- Configuration config = new Configuration().configure();
- SessionFactory sessionFactory = config.buildSessionFactory();
- Session session = sessionFactory.openSession();
-
- String hql = "from com.hb3.pack_22.model.User";
-
- Query query = session.createQuery(hql);
-
- List> list = query.list();
- Iterator> iterator = list.iterator();
- while (iterator.hasNext()) {
- User user = (User)iterator.next();
- System.out.println(user.getRoom().getAddress());
- }
-
- query = session.createQuery(hql);
- System.out.println("=====================================");
- iterator = query.iterate();
- while (iterator.hasNext()) {
- User user = (User)iterator.next();
- System.out.println(user.getName());
- }
-
- session.close();
- sessionFactory.close();
- }
- }
执行的结果为:
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会大大提高性能。