tags: Mybatisjava
缓存的意义spring
mybatis提供一级缓存和二级缓存sql
看完上面对Mybatis的缓存的解释,咱们发现Mybatis的缓存和Hibernate的缓存是极为类似的..数据库
Mybatis的一级缓存原理:apache
第一次发出一个查询sql,sql查询结果写入sqlsession的一级缓存中,缓存使用的数据结构是一个map<key,value>缓存
同一个sqlsession再次发出相同的sql,就从缓存中取不走数据库。若是两次中间出现commit操做(修改、添加、删除),本sqlsession中的一级缓存区域所有清空,下次再去缓存中查询不到因此要从数据库查询,从数据库查询到再写入缓存。安全
Mybatis一级缓存值得注意的地方:session
二级缓存原理:数据结构
二级缓存的范围是mapper级别(mapper同一个命名空间),mapper以命名空间为单位建立缓存数据结构,结构是map<key、value>。mybatis
须要咱们在Mybatis的配置文件中配置二级缓存
<!-- 全局配置参数 -->
<settings>
<!-- 开启二级缓存 -->
<setting name="cacheEnabled" value="true"/>
</settings>
复制代码
上面已经说了,二级缓存的范围是mapper级别的,所以咱们的Mapper若是要使用二级缓存,还须要在对应的映射文件中配置..
<cache/>
复制代码
mybatis二级缓存须要将查询结果映射的pojo实现 java.io.serializable接口,若是不实现则抛出异常:
org.apache.ibatis.cache.CacheException: Error serializing object. Cause: java.io.NotSerializableException: cn.itcast.mybatis.po.User
复制代码
二级缓存能够将内存的数据写到磁盘,存在对象的序列化和反序列化,因此要实现java.io.serializable接口。 若是结果映射的pojo中还包括了pojo,都要实现java.io.serializable接口。
对于变化频率较高的sql,须要禁用二级缓存:
在statement中设置useCache=false能够禁用当前select语句的二级缓存,即每次查询都会发出sql去查询,**默认状况是true,**即该sql使用二级缓存。、、
<select id="findOrderListResultMap" resultMap="ordersUserMap" useCache="false">
复制代码
有的同窗到这里可能会有一个疑问:为何缓存咱们都是在查询语句中配置??而使用增删改的时候,缓存默认就会被清空【刷新了】???
缓存其实就是为咱们的查询服务的,对于增删改而言,若是咱们的缓存保存了增删改后的数据,那么再次读取时就会读到脏数据了!
咱们在特定的状况下,还能够单独配置刷新缓存【但不建议使用】flushCache,默认是的true
<update id="updateUser" parameterType="cn.itcast.mybatis.po.User" flushCache="false">
update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} where id=#{id}
</update>
复制代码
mybatis的cache参数只适用于mybatis维护缓存。
flushInterval(刷新间隔)能够被设置为任意的正整数,并且它们表明一个合理的毫秒形式的时间段。默认状况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新。
size(引用数目)能够被设置为任意正整数,要记住你缓存的对象数目和你运行环境的可用内存资源数目。默认值是1024。
readOnly(只读)属性能够被设置为true或false。只读的缓存会给全部调用者返回缓存对象的相同实例。所以这些对象不能被修改。这提供了很重要的性能优点。可读写的缓存会返回缓存对象的拷贝(经过序列化)。这会慢一些,可是安全,所以默认是false。
以下例子:
<cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>
这个更高级的配置建立了一个 FIFO 缓存,并每隔 60 秒刷新,存数结果对象或列表的 512 个引用,并且返回的对象被认为是只读的,所以在不一样线程中的调用者之间修改它们会致使冲突。可用的收回策略有, 默认的是 LRU:
1.LRU – 最近最少使用的:移除最长时间不被使用的对象。
2.FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
3.SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。
4.WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。
复制代码
ehcache是专门用于管理缓存的,Mybatis的缓存交由ehcache管理会更加得当..
在mybatis中提供一个cache接口,只要实现cache接口就能够把缓存数据灵活的管理起来。
ehcache对cache接口的实现类:
这个xml配置文件是配置全局的缓存管理方案
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
<!--diskStore:缓存数据持久化的目录 地址 -->
<diskStore path="F:\develop\ehcache" />
<defaultCache maxElementsInMemory="1000" maxElementsOnDisk="10000000" eternal="false" overflowToDisk="false" diskPersistent="true" timeToIdleSeconds="120" timeToLiveSeconds="120" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU">
</defaultCache>
</ehcache>
复制代码
若是咱们Mapper想单独拥有一些特性,须要在mapper.xml中单独配置
<!-- 单位:毫秒 -->
<cache type="org.mybatis.caches.ehcache.EhcacheCache">
<property name="timeToIdleSeconds" value="12000"/>
<property name="timeToLiveSeconds" value="3600"/>
<!-- 同ehcache参数maxElementsInMemory -->
<property name="maxEntriesLocalHeap" value="1000"/>
<!-- 同ehcache参数maxElementsOnDisk -->
<property name="maxEntriesLocalDisk" value="10000000"/>
<property name="memoryStoreEvictionPolicy" value="LRU"/>
</cache>
复制代码
对查询频率高,变化频率低的数据建议使用二级缓存。
对于访问多的查询请求且用户对查询结果实时性要求不高,此时可采用mybatis二级缓存技术下降数据库访问量,提升访问速度
业务场景好比:
实现方法以下:经过设置刷新间隔时间,由mybatis每隔一段时间自动清空缓存,根据数据变化频率设置缓存刷新间隔flushInterval,好比设置为30分钟、60分钟、24小时等,根据需求而定。
mybatis局限性
mybatis二级缓存对细粒度的数据级别的缓存实现很差,好比以下需求:对商品信息进行缓存,因为商品信息查询访问量大,可是要求用户每次都能查询最新的商品信息,此时若是使用mybatis的二级缓存就没法实现当一个商品变化时只刷新该商品的缓存信息而不刷新其它商品的信息,由于mybaits的二级缓存区域以mapper为单位划分,当一个商品信息变化会将全部商品信息的缓存数据所有清空。解决此类问题须要在业务层根据需求对数据有针对性缓存。
若是您以为这篇文章帮助到了您,能够给做者一点鼓励