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