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();
    }
原文地址:https://www.cnblogs.com/ZHONGZHENHUA/p/6708443.html