day37 04-Hibernate二级缓存:list和iterate方法比较
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();
}
浙公网安备 33010602011771号