什么是缓存
缓存cache:计算机领域非常通用的概念。它介于应用程序和永久性数据存储源(如硬盘的文件或者数据库)之间,其作用是降低应用程序直接读写硬盘(永久性数据存储源)的频率,从而提高应用的运行性能,缓存中的数据是数据存储源中的数据拷贝。缓存的物理介质通常是内存。
缓存:程序《-----(内存)----》硬盘
二级缓存
hibernate的一级缓存也叫session级别缓存,在一次请求中共享数据。
hibernate的二级缓存,sessionFactory级别的缓存,整个应用程序共享一个会话工厂,共享一个二级缓存。
sessionFactory的缓存又分为内置缓存和外置缓存。
内置缓存:使用一个Map,用于存放配置信息,预定义HQL语句等,提供Hibernate框架自己使用,对外只读,不能操作
外置缓存:使用另一个Map,用于存放用户自定义数据,默认不开启外置缓存,hibernate只提供规范(接口),需要第三方实现类,外置缓存也被称为二级缓存
二级缓存的架构
二级缓存的四大部分分别是:类级别缓存、集合级别缓存、时间戳缓存、查询缓存。
并发访问策略
应用场景
适用放在二级缓存中的数据,很少被修改,不是很重要的数据,允许出现偶尔的并发问题
不适合存在二级缓存的数据,经常被修改,比如财务数据,绝对不允许出现并发问题,与其他应用数据共享的数据
二级缓存提供商
Hibernate中只定义二级缓存接口,实现需要自己选择提供商。
EHCache:可作为进程(单机)范围内的缓存,存放数据的物理介质,可以是内存或硬盘对Hibernate的查询缓存提供了支持,支持集群。
OpenSymphony:可作为进程范围内的缓存,存放数据的物理介质,可以是内存或硬盘。提供了丰富的缓存数据过期策略。对Hibernate的查询缓存提供了支持。
SwarmCache:可作为集群范围内的缓存,但不支持HIbernate的查询缓存
JBOSSCache:可作为集群范围内的缓存,支持Hibernate的查询缓存
hibernate缓存实战
首先在hibernate项目中导入ehcache相关的jar包,如下图所示:
类级别缓存
<property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
<property name="hibernate.cache.use_second_level_cache">true</property>
<class-cache class="com.zzx.hibernate.domain.Customer" usage="read-only"/>
<class-cache class="com.zzx.hibernate.domain.Order" usage="read-only"/>
然后把jar包中的ehcache failsafe.xml文件复制到项目中的src目录,然后改名为ehcache.xml
ehcache设置临时文件存放位置(缓存一般内存,一定程度时,写入硬盘)
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
maxElementsOnDisk="10000000"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU"
/>
ehcache属性详解
maxElementsInMemory:设置基于内存的缓存中可存放的对象,最大数目
eternal:设置对象是否为永久的,true标识永久不过期,此时将忽略
timeToIdleSeconds和timeToLiveSeconds属性,默认值是false
timeToIdleSeconds:设置对象空闲最长时间,以秒为单位,超过这个时间,对象过期。当对象过期时,EHCache会把它的缓存清除。如果这个值为0,表示对象可能无限期的处于空闲状态。
timeToLiveSeconds:设置对象生成最长时间,超过这个时间,对象过期,如果此值为0,标识对象可能无限地存在于缓存中,该属性必须大于或等于timeToIdleSeconds属性值。
overflowToDisk:设置基于存在缓存中的对象的数目达到上限后是否把溢出的对象写在基于硬盘的缓存中。
diskPersistent:当JVM结束时是否持久化对象true或false 默认是false。
diskExpiryThreadIntervalSeconds:指定专门用于清除过期对象的监听线程的轮询时间。
memoryStoreEvictionPolicy:当内存缓存达到最大,有新的element加入的时候。移除缓存中element的策略。默认是LRU(最近最少使用,可选的有LFO(最不常使用)和FIFO(先进先出))
类缓存只存放散装数据,一级缓存存放对象本身
配置集合缓存
<!--配置集合缓存-->
<collection-cache collection="com.zzx.hibernate.domain.Customer.orders" usage="read-only"></collection-cache>
查询缓存
查询缓存又称为三级缓存,在默认情况下hibernate没有被使用,需要手动开启,它将HQL语句和查询结果进行绑定,通过HQL相同语句可以缓存内容。默认情况下Query只将查询结果存放在一级和二级缓存,不从一级或二级缓存获取数据。
查询缓存就是让Query可以从二级缓存获取内容。
开启查询缓存
<property name="hibernate.cache.use_query_cache">true</property>
查询缓存案例:
Session session = HibernateUtil.openSession();
Query query = session.createQuery("from Customer");
query.setCacheable(true);
List<Customer> customerList = query.list();
System.out.println(customerList);
session.close();
Session session2 = HibernateUtil.openSession();
Query query2 = session2.createQuery("from Customer");
query2.setCacheable(true);
List<Customer> list = query2.list();
System.out.println(list);
session2.close();
控制台输出结果查询
Hibernate:
select
customer0_.id as id0_,
customer0_.version as version0_,
customer0_.name as name0_
from
t_customer customer0_
[Customer{id=1, name='zhangsan', version=0}, Customer{id=2, name='武松', version=0}, Customer{id=3, name='杜十娘', version=0}, Customer{id=4, name='林冲', version=0}]
[Customer{id=1, name='zhangsan', version=0}, Customer{id=2, name='武松', version=0}, Customer{id=3, name='杜十娘', version=0}, Customer{id=4, name='林冲', version=0}]
从上面的结果我们不难看出,执行两次查询结果操作,实际只调用了一次数据库查询
时间戳查询
任何操作都在时间戳中记录操作时间