hibernate查询缓存
自:http://blog.sina.com.cn/s/blog_614cb62d0100fkp6.html
查询缓存的生命周期,当查询关联的表发生改变,那么查询缓存的生命周期结束(delete、update、modify)
启用查询缓存:
1.hibernate.cfg.xml中配置:<propertyname="cache.use_query_cache">true</property>
2.代码中用setCacheable(true)手动启用
只对list()方法起作用
默认情况下list()每次都会发SQL语句,只有配置了查询缓存它才会利用缓存。
实例
一、查询普通属性
1.查询普通属性,开启二级缓存和查询缓存,在同一个session中和不同session中
代码:
Sessionsession=this.sf.openSession();
Listlist=session.createQuery("selectidfromOrder")
.setCacheable(true)
.list();
System.out.println("数量:"+list.size());
//session.close();
//session=this.sf.openSession();
Listl=session.createQuery("selectidfromOrder")
.setCacheable(true)
.list();
System.out.println("数量:"+l.size());
session.close();
执行结果都一样,所以查询缓存的生命周期与session无关:
Hibernate:
select
order0_.idascol_0_0_
from
t_orderorder0_
数量:3
数量:3
2.查询普通属性,关闭二级缓存,开启查询缓存,在同一个session中
代码同1
执行结果:
Hibernate:
select
order0_.idascol_0_0_
from
t_orderorder0_
数量:3
数量:3
3.查询普通属性,开启二级缓存,关闭查询缓存,在同一个session中
代码:
Sessionsession=this.sf.openSession();
Listlist=session.createQuery("selectidfromOrder")
.setCacheable(false)
.list();
System.out.println("数量:"+list.size());
Listl=session.createQuery("selectidfromOrder")
.setCacheable(false)
.list();
System.out.println("数量:"+l.size());
session.close();
执行结果:
Hibernate:
select
order0_.idascol_0_0_
from
t_orderorder0_
数量:3
Hibernate:
select
order0_.idascol_0_0_
from
t_orderorder0_
数量:3
二、查询实体对象
1.关闭二级缓存和查询缓存,在同一个session中
代码:
publicvoidtest1(){
Sessionsession=this.sf.openSession();
Listlist=session.createQuery("fromOrder")
.list();
System.out.println("数量:"+list.size());
Listl=session.createQuery("fromOrder")
.list();
System.out.println("数量:"+l.size());
session.close();
}
执行结果:
Hibernate:
select
order0_.idasid1_,
order0_.orderNumasorderNum1_,
order0_.fk_user_idasfk3_1_
from
t_orderorder0_
数量:3
Hibernate:
select
order0_.idasid1_,
order0_.orderNumasorderNum1_,
order0_.fk_user_idasfk3_1_
from
t_orderorder0_
数量:3
2.关闭二级缓存,开启查询缓存,在同一个session中
代码:
Sessionsession=this.sf.openSession();
Listlist=session.createQuery("fromOrder")
.setCacheable(true)
.list();
System.out.println("数量:"+list.size());
Listl=session.createQuery("fromOrder")
.setCacheable(true)
.list();
System.out.println("数量:"+l.size());
session.close();
执行结果:
Hibernate:
select
order0_.idasid1_,
order0_.orderNumasorderNum1_,
order0_.fk_user_idasfk3_1_
from
t_orderorder0_
数量:3
数量:3
之所以第二次不发出SQL语句,是因为在同一个session中,实体对象保存到了一级缓存中;而查询缓存中保存了实体对象的id列表,第二次查询就根据id从一级缓存中取得数据。开启二级缓存,开启查询缓存,在不同session中也是这样的结果,只是实体对象保存到了二级缓存中,第二次查询从二级缓存中去找。
3.关闭二级缓存,开启查询缓存,在两个session中
代码:
Sessionsession=this.sf.openSession();
Listlist=session.createQuery("fromOrder")
.setCacheable(true)
.list();
System.out.println("数量:"+list.size());
session.close();
//第二个session
session=this.sf.openSession();
Listl=session.createQuery("fromOrder")
.setCacheable(true)
.list();
System.out.println("数量:"+l.size());
session.close();
执行结果:
Hibernate:
select
order0_.idasid1_,
order0_.orderNumasorderNum1_,
order0_.fk_user_idasfk3_1_
from
t_orderorder0_
数量:3
Hibernate:
select
order0_.idasid1_0_,
order0_.orderNumasorderNum1_0_,
order0_.fk_user_idasfk3_1_0_
from
t_orderorder0_
where
order0_.id=?
Hibernate:
select
order0_.idasid1_0_,
order0_.orderNumasorderNum1_0_,
order0_.fk_user_idasfk3_1_0_
from
t_orderorder0_
where
order0_.id=?
Hibernate:
select
order0_.idasid1_0_,
order0_.orderNumasorderNum1_0_,
order0_.fk_user_idasfk3_1_0_
from
t_orderorder0_
where
order0_.id=?
数量:3
这种情况下,当第二次查询执行的时候,在二级缓存和一级缓冲中都找不到实体对象,所以list()只有拿着id到数据库中一个一个找,于是产生了N+1问题。
结论:
1.查询缓存是对普通属性结果集的缓存
2.对实体对象的缓存集只缓存id