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号
浙公网安备 33010602011771号