get()和load()方法既可以向一级缓存区放数据,也可以向二级缓存区放数据。这是查询一个的情况。要是查询所有呢?注意,
// 查询所有.Query接口的list()方法.
// list()方法会向二级缓存中放数据,但是不会使用二级缓存中的数据.
//list()方法没有使用二级缓存的数据.
没有发生SQL,证明肯定是从一级缓存或者是二级缓存获取的数据.一级缓存没有,那肯定是从二级缓存获取的.有人说那这list()方法的效率就比较低了。一级缓存经常使用list(),但是有了二级缓存如果你想查询所有,可以用另外一个方法。
如果没有二级缓存,不建议使用iterate()(因为效率会比较低),迭代器的方法。
// iterate()方法可以查询所有信息.
// iterate方法会发送N+1条SQL查询.但是会使用二级缓存的数据
// N+1条SQL去查询.
iterate()的效果:
Hibernate:
select
customer0_.cid as col_0_0_
from
customer customer0_
Hibernate:
select
customer0_.cid as cid0_0_,
customer0_.version as version0_0_,
customer0_.cname as cname0_0_,
customer0_.age as age0_0_
from
customer customer0_
where
customer0_.cid=?
Customer [cid=1, cname=小金, age=23, ver=0]
Hibernate:
select
customer0_.cid as cid0_0_,
customer0_.version as version0_0_,
customer0_.cname as cname0_0_,
customer0_.age as age0_0_
from
customer customer0_
where
customer0_.cid=?
Customer [cid=2, cname=小明, age=32, ver=0]
Hibernate:
select
customer0_.cid as cid0_0_,
customer0_.version as version0_0_,
customer0_.cname as cname0_0_,
customer0_.age as age0_0_
from
customer customer0_
where
customer0_.cid=?
Customer [cid=3, cname=沈明贞, age=28, ver=1]
Hibernate:
select
customer0_.cid as cid0_0_,
customer0_.version as version0_0_,
customer0_.cname as cname0_0_,
customer0_.age as age0_0_
from
customer customer0_
where
customer0_.cid=?
Customer [cid=4, cname=张三, age=28, ver=0]
Hibernate:
select
customer0_.cid as cid0_0_,
customer0_.version as version0_0_,
customer0_.cname as cname0_0_,
customer0_.age as age0_0_
from
customer customer0_
where
customer0_.cid=?
Customer [cid=5, cname=张三, age=28, ver=0]
如果没有二级缓存,iterate()方法效率比较低。因为执行Iterator<Customer> iterator = session.createQuery("from Customer").iterate();调用iterate()只查询所有客户的id。当你每次迭代的时候它才会根据你每个客户的id去查询客户的信息。所以iterate()是一个N+1条SQL去查询。你有N条记录,它会发N+1条SQL去查询。第一条是查询所有的id,然后再根据id逐一检索。所以这个方法效率比较低。list()方法效率高,直接全部都查出来了。
但是list()有了二级缓存,效率就比不上iterate()。因为iterate()可以使用二级缓存的数据。
开放/配置二级缓存
<!-- Hibernate中开启二级缓存 -->
<property name="hibernate.cache.use_second_level_cache">true</property>
<!-- 配置二级缓存的提供商 -->
<property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
<!-- 配置哪些类使用二级缓存 -->
<class-cache usage="read-write" class="cn.itcast.hibernate3.demo1.Customer"/>
<!--查询订单的类缓存区-->
<class-cache usage="read-write" class="cn.itcast.hibernate3.demo1.Order"/>
之后,iterate()的效果:
Hibernate:
select
customer0_.cid as col_0_0_
from
customer customer0_
Customer [cid=1, cname=小金, age=23, ver=0]
Customer [cid=2, cname=小明, age=32, ver=0]
Customer [cid=3, cname=沈明贞, age=28, ver=1]
Customer [cid=4, cname=张三, age=28, ver=0]
Customer [cid=5, cname=张三, age=28, ver=0]
还是会发送SQL语句查询所有客户的id,但是在根据客户的id检索每一条记录的时候就直接打印了,而没有再发生SQL去查询。所以iterate()是可以使用二级缓存的。
结论:
在查询所有的时候,如果有二级缓存,使用iterate(),如果没有二级缓存,使用list().
@SuppressWarnings("unchecked") @Test // iterate()方法可以查询所有信息. // iterate方法会发送N+1条SQL查询.但是会使用二级缓存的数据 public void demo5(){ Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); // N+1条SQL去查询. Iterator<Customer> iterator = session.createQuery("from Customer").iterate(); while(iterator.hasNext()){ Customer customer = iterator.next(); System.out.println(customer); } tx.commit(); session = HibernateUtils.getCurrentSession(); tx = session.beginTransaction(); iterator = session.createQuery("from Customer").iterate(); while(iterator.hasNext()){ Customer customer = iterator.next(); System.out.println(customer); } tx.commit(); } @SuppressWarnings("unchecked") @Test // 查询所有.Query接口的list()方法. // list()方法会向二级缓存中放数据,但是不会使用二级缓存中的数据. public void demo4(){ Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); // 查询所有客户: // list方法会向二级缓存中放入数据的. List<Customer> list = session.createQuery("from Customer").list(); for (Customer customer : list) { System.out.println(customer.getCname()); } tx.commit(); session = HibernateUtils.getCurrentSession(); tx = session.beginTransaction(); Customer customer = (Customer) session.get(Customer.class, 1);// 没有发生SQL ,从二级缓存获取的数据. //list()方法没有使用二级缓存的数据. /* list = session.createQuery("from Customer").list(); for (Customer customer : list) { System.out.println(customer.getCname()); }*/ tx.commit(); }