查询缓存
对于经常实用的查询语句,如果启用了查询缓存,当第一次执行查询语句时,Hibernate会把查询结果存放在查询缓存中,以后再次执行该查询语句时,只需从缓存中获得查询结果,从而提高查询性能
查询缓存使用如下场合:- 应用程序运行时经常使用查询语句
- 很少对与查询语句检索到的数据进行插入,删除和更新操作
- 配置二级缓存,因为查询缓存依赖于二级缓存
- 在hibernate配置文件中启用查询缓存:<property name="cache.use_query_cache">true</property>
- 对于希望启用查询缓存的查询语句,调用Query的setCacheable()方法
<!--
查询缓存:默认情况下,设置的缓存对HQL 及 QBC 查询是无效的,但可以通过以下方式使其是有效地
第一步:在hibernate 配置文件中声明开启查询缓存
<property name="cache.use_query_cache">true</property>
第二步:调用Query或Criteria 的setCacheable(true)方法
第三步:配置二级缓存(查询缓依赖二级缓存)
-- >
@Test
public void testQueryCache(){
Query query =session.createQuery("FROM Employee");
query.setCacheable(true);
List<Employee> emps=query.list();
System.out.println(emps.size());
Criteria criteria= session.queryCriteria(Employee.class);
criteria.setCacheable(true);
}
时间戳缓存区域
时间戳缓存区域存放了对于查询结果相关的表进行插入,更新或删除操作的时间戳。hibernate通过时间戳缓存区域来判断被缓存的查询结果是否过期,其运行过程如下:- T1时刻执行查询操作,把查询结果存放在QueryCache区域,记录该区域的时间为T1
- T2时刻对查询结果相关的表进行更新操作,Hibernate把T2时刻存放在UpdateTimestampCache区域
- T3时刻执行查询结果前,先比较QueryCache区域的时间戳和UpdateTimestampCache区域的时间戳,若T2>T1,那么就丢弃原先存放在QueryCache区域的查询结果,重新到数据库中查询数据,再把结果存方法到QueryCache区域;若T2 < T1,直接从QueryCache中获得查询结果
@Test
public void testTimestampCache(){
Query query =session.creatQuery("FROM Employess");
List<Employee> emps=query.list();
System.out.println(emps.size());
Employee employee=(Employee) session.get(Employee.class,100);
employee.setSalary(30000);
emps=query.list();
System.out.println(emps.size());
}
//打印结果:会打印select语句,update语句,select语句三条sql语句
Query接口的iterator()方法
Query接口的iterator()方法- 同list()一样也能执行查询操作
- list()方法执行的SQL语句包含实体类对应的数据表的所有字段
- iterator()方法执行的SQL语句中仅包含实体类对应的数据表的ID字段
- 当遍历访问结果集时,该方法先到Session缓存及二级缓存中查看是否存在特定OID的对象,如果存在,就直接返回该对象,如果不存在该对象就通过相应的SQL Select语句到数据库中加载特定的实体对象
iterator()方法仅在满足以下条件的场合,可以 稍微提高查询性能
- 要查询的数据表中包含大量字段
- 启用二级缓存,且二级缓存中可能包含了待查询的对象
@Test
public void testQueryIterator(){
Department dept=(Department) session.get(Department.class,80);
System.out.println(dept.getName());
System.out.println(dept.getEmps().size());
Query query =session.createQuery("FROM Employee e WHERE e.dept.id=80");
// List<Employee> emps=query.list();
// System.out.println(emps.size());
Iterator<Employee> emp2=query.iterate();
while(emp2.hasNext()){
System.out.println(emp2.next().getName());
}