Hibernate 缓存机制
一级缓存
简介
一级缓存是session级别的缓存,只在session的范围内有效
案例一:代码分析
控制台打印您就会发现只有一条SQL语句,通过 list() 集合的方式放入在 session 一级缓存中, 当再次查询用户信息时,会首先去 session 缓存中看是否存在,如果存在就直接在缓存中获取。如果不存在,再去数据库中查询
List<User> users = (List<User>)session.createQuery("from User ").setFirstResult(0).setMaxResults(30).list();
Iterator<User> iterator = users.iterator();
while (iterator.hasNext()) {
User user = iterator.next();
System.out.println(user.toString());
}
// 控制台SQL打印
Hibernate:
select
user0_.id as id1_0_,
user0_.username as username2_0_,
user0_.age as age3_0_
from
tb_user user0_ limit ?
案例二:代码分析
控制台SQL打印就会发现打印 n 多条SQL语句,数据库有 n 条数据就打印 n 条SQL语句, 使用迭代器查询数根据 ID 主键查询。查到一次后放入到 session 缓存中,如果 session 缓存中有 n 条数据,就会一次缓存查询 n 次
Iterator<User> users = (Iterator<User>)session.createQuery("from User ").setFirstResult(0).setMaxResults(30).iterate();
for(;users.hasNext();) {
User user = users.next();
System.out.println(user.toString());
}
疑点
如果我们在查询到结果后,如果把 session 缓存关闭,就意味着 session 缓存不存在。下回再查就会一下次 n 多条查询SQL,如果要查询几百万条数据,直接爆炸。所以我们要引入二级缓存
二级缓存
简介
二级缓存是 sessionFactory 级别的缓存,也称为进程级别的缓存,在所有的session中都有效
在配置文件 hibernate.cfg.xml 引入
<!-- 开启二级缓存 -->
<property name ="hibernate.cache.use_second_level_cache">true </property>
<!-- 二级缓存的提供类 -->
<property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory</property>
<!-- 二级缓存配置文件的位置 -->
<property name="hibernate.cache.provider_configuration_file_resource_path">ehcache.xml</property>
引入 ehcache.cfg.xml 配置文件
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
updateCheck="false">
<diskStore path="java.io.tmpdir/ehcache" />
<defaultCache
eternal="false"
maxElementsInMemory="10000"
overflowToDisk="false"
diskPersistent="false"
timeToIdleSeconds="1800"
timeToLiveSeconds="259200"
/>
<cache name="priv.linyu.hibernate.entity.User"
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
overflowToDisk="true"
/>
<!-- <cache name="sampleCache2"
maxElementsInMemory="1000"
eternal="true"
timeToIdleSeconds="0"
timeToLiveSeconds="0"
overflowToDisk="false"
/> -->
</ehcache>
使用 User.hbm.xml 编写
<class name="priv.linyu.hibernate.entity.User" table="tb_user" schema="db_test">
<!--
方式1:
引入二级缓存
1.read-only:只读
2.nonstrict-read-write:非严格读
3.read-write:读写
4.transactional:事务
方式2:在实体类上加上:@Cache(usage=CacheConcurrencyStrategy.READ_ONLY)
-->
<cache usage="read-only" />
...
</class>
解析
由于二级缓存是sessionFactory级别的缓存,在配置了二级缓存以后,当session关闭以后,再去查询对象的时候,此时hibernate首先会去二级缓存中查询是否有该对象,有就不会再发sql了, 但问题是二级缓存缓存的仅仅是对象,如果查询出来的是对象的一些属性,则不会被加到缓存中去。引入一个查询缓存就可以很好解决这个问题
查询缓存
简介
查询缓存依赖于二级缓存,在HQL的查询语句中生效
在配置文件 hibernate.cfg.xml 引入
<!-- 开启查询缓存 -->
<property name="hibernate.cache.use_query_cache">true</property>

浙公网安备 33010602011771号