查询缓存:
首先明确查询缓存缓存的是什么?缓存的 key 是 HQL 语句与参数,缓存的 value 则是:
1、 如果查询的是普通结果集,则缓存这些结果集
2、 如果查询的是实体对象,则缓存的是实体对象的 ID 列表
3、 查询缓存它也是 SessionFactory 级别的缓存,由 sessionFactory 管理
现在看看使用查询缓存的三个步骤:
1、 在 Hibernate 配置文件中,启用查询缓存
<!-- 配置打开查询缓存 -->
<property name="hibernate.cache.use_query_cache">true</property>
2、 提供查询缓存的策略提供商,一般跟二级缓存的提供商是一样的
<!-- 指定二级缓存和查询缓存的具体实现! -->
<property name="hibernate.cache.provider_class">
org.hibernate.cache.HashtableCacheProvider</property>
3、 查询之前调用 Query.setCacheable(true) ,这样查询缓存就起作用了。举个例子如下:
session.beginTransaction();
//查询缓存是SessionFactory级别的缓存
String hql = "select p.id,p.name from Person p";
List persons = session.createQuery(hql)
.setCacheable(true) //允许查询缓存!
.list();
for (Iterator iterator = persons.iterator(); iterator.hasNext();) {
Object[] datas = (Object[]) iterator.next();
System.out.println(datas[0]+","+datas[1]);
}
session.getTransaction().commit();
}catch(Exception e){
e.printStackTrace();
session.getTransaction().rollback();
}finally{
//session关闭之后,当前session对象中的一级缓存已经被清空
session.close();
}
Session session2 = HibernateUtil.openSession();
try{
session2.beginTransaction();
String hql = "select p.id,p.name from Person p";
//不发出sql语句
List persons = session2.createQuery(hql)
.setCacheable(true) //允许查询缓存!
.list();
for (Iterator iterator = persons.iterator(); iterator.hasNext();) {
Object[] datas = (Object[]) iterator.next();
System.out.println(datas[0]+","+datas[1]);
}
session2.getTransaction().commit();
接下来继续研究下:如果查询的参数不一致呢?
session.beginTransaction();
//如果查询参数不一样,最好不要使用查询缓存
String hql = "select p.id,p.name from ContactPerson p where p.name like ?";
List persons = session.createQuery(hql)
.setParameter(0, "%巴%")
.setCacheable(true) //允许查询缓存!
.list();
session2.beginTransaction();
String hql = "select p.id,p.name from ContactPerson p where p.name like ?";
List persons = session2.createQuery(hql)
.setParameter(0, "%特%")
.setCacheable(true) //允许查询缓存!
.list();
上面会发两条 sql 语句,因为查询的参数不一致。
查询缓存的 1+N 问题见 1+N 问题的文章!
总结:
- 要注意,查询缓存一般配合二级缓存一起使用
- 如果查询条件及其参数非常容易发生变化,请慎用查询缓存
- 注意理解查询缓存中的 N 个查询的问题!