MyBatis缓存

目录

一级缓存

一级缓存原理

一级缓存配置

二级缓存

二级缓存原理

缓存对象策略

二级缓存的具体流程

二级缓存配置

通过application.yml配置

通过MyBatis配置

通过xxxMapper.xml 配置

 不更新二级缓存

如何验证 

第三方缓存框架ehcache

ehcache简介

MyBatis整合ehcache

添加ehcache依赖

配置Ehcache

修改XxxMapper.xml文件 


针对一些经常查询但不经常改变的数据,如果每次查询都与数据库进行交互,将大大降低查询效率,因此可以引入缓存,将这些数据存放在内存中,从而减少与数据库交互来提高效率。

一级缓存

一级缓存默认开启,缓存一般是针对{增删改查}的查

SqlSession级别的缓存,缓存的数据只在SqlSession内有效。
一级缓存mybatis已近为我们自动开启,不用我们手动操作,而且我们是关闭不了的!!但是我们可以手动清除缓存。一级缓存是sqlSession级别的缓存。在操作数据库时需要构造sqlSession对象,在对象中有一个基于 PerpetualCache的HashMap 本地缓存数据结构,用于缓存数据。不同的sqlSession之间的缓存数据区域(HashMap)是互不影响的。
 

一级缓存原理

1、第一次查询用户id为1的用户信息,先去缓存中查询是否有id为1的用户信息,如果没有,从数据库中查询用户信息。得到用户信息后在将用户信息储存到一级缓存中。


2、如果sqlSession去执行commit操作(插入、更新、删除),清空sqlSession中的一级缓存,保证缓存中始终保存的是最新的信息,避免脏读。


3、第二次查询用户id为1的用户信息,先去缓存中查询是否有id为1的用户信息,如缓存中有,直接从缓存中获取。


4、注意:两次查询须在同一个sqlsession中完成,否则将不会走mybatis的一级缓存。在mybatis与spring进行整合开发时,事务控制在service中进行,重复调用两次servcie将不会走一级缓存,因为在第二次调用时session方法结束,SqlSession就关闭了

注意事项:

mybatis默认是开启一级缓存,不需要配置
如果SqlSession执行了DML操作(insert、update、delete),并commit了,那么mybatis就会清空当前SqlSession缓存中的所有缓存数据,这样可以保证缓存中存的数据永远和数据库中一致,避免出现脏读
一个SqlSession结束后那么它里面的一级缓存也就不存在了。
mybatis的缓存是基于 [ namespace:sql语句:参数 ] 来进行缓存的。意思就是,SqlSession的HashMap存储缓存数据时,是使用 [ namespace:sql:参数 ] 作为key,查询返回的语句作为value保存的。

一级缓存配置

一级缓存默认开启,如果不想使用一级缓存,可以修改配置进行关闭

<select id="selectUserById" resultMap="map" useCache="false">

二级缓存

mapper级别的缓存,同一个namespace公用这一个缓存,所以对SqlSession是共享的。
二级缓存需要我们手动开启。(全局级别) 二级缓存是mapper级别的缓存,多个sqlSession去操作同一个Mapper的sql语句,多个sqlSession可以共用二级缓存,二级缓存是跨sqlSession的。
 

二级缓存原理

二级缓存与一级缓存原理相同,默认也是采用 PerpetualCache,HashMap 存储,不同在于其存储作用域为 Mapper ( Namespace ),并且可自定义存储源,如 Ehcache。作用域为 namespance 是指对该 namespance 对应的配置文件中所有的 select 操作结果都缓存,这样不同线程之间就可以共用二级缓存。


缓存对象策略

readOnly=“true”(只读):MyBatis 认为所有从缓存中获取数据的操作都是只读操作,不会修改数据。MyBatis 为了加快获取数据,直接就会将数据在缓存中的引用交给用户 。不安全,速度快。


readOnly=“false”(读写,默认):MyBatis 觉得获取的数据可能会被修改,MyBatis 会利用序列化或反序列化的技术克隆一份新的数据。安全,速度相对慢。


二级缓存是基于映射文件的缓存(namespace),缓存范围比一级缓存更大,不同的SQLSession可以访问二级缓存的内容。哪些数据放入二级缓存需要自己指定。

二级缓存的具体流程

当一个sqlseesion执行了一次select后,关闭此session的时候,会将查询结果缓存到二级缓存
当另一个sqlsession执行select时,首先会在他自己的一级缓存中找,如果没找到,就回去二级缓存中找,找到了就返回,就不用去数据库了,从而减少了数据库压力提高了性能。

注意事项:

如果SqlSession执行了DML操作(insert、update、delete),并commit了,那么mybatis就会清空当前mapper缓存中的所有缓存数据,这样可以保证缓存中的存的数据永远和数据库中一致,避免出现脏读
mybatis的缓存是基于[ namespace:sql语句:参数 ]来进行缓存的,意思就是,SqlSession的HashMap存储缓存数据时,是使用[ namespace:sql:参数 ]作为key,查询返回的语句作为value保存的。
 

二级缓存配置

如下三种方式任选其一即可

通过application.yml配置

# mybatis相关配置
mybatis:
  configuration:
      log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
      #开启MyBatis的二级缓存
      cache-enabled: true

通过MyBatis配置

在MyBatis-config.xml 文件中添加如下代码

<setting name="cacheEnabled" value="true"/>

通过xxxMapper.xml 配置

<cache eviction="FIFO" flushInterval="60000" readOnly="false" size="1024"/>

eviction:缓存的回收策略,默认的是 LRU。

  • LRU - 最近最少使用,移除最长时间不被使用的对象。
  • FIFO - 先进先出,按对象进入缓存的顺序来移除它们。
  • SOFT - 软引用,移除基于垃圾回收器状态和软引用规则的对象。
  • WEAK - 弱引用,更积极地移除基于垃圾收集器和弱引用规则的对象。

flushInterval:缓存刷新间隔。缓存多长时间清空一次,默认不清空,设置一个毫秒值。

readOnly:是否只读。

  • true(只读):
  • false(读写,默认)

size:缓存存放多少个元素。

type:指定自定义缓存的全类名(实现 Cache 接口即可)。PS:要使用二级缓存,对应的 POJO 必须实现序列化接口 

不更新二级缓存

二级缓存默认会在 insert、update、delete 操作后刷新缓存。但可以手动配置不更新缓存

<update id="updateUserById" parameterType="User" flushCache="false">

如何验证 

开启二级缓存成功之后,DEBUG日志会会打印缓存命中日志

[MybatisQueriesLogImpl.java.debug:37] [Cache Hit Ratio [com.xm.mer.dao.ADao]: 0.9992005159695255]

第三方缓存框架ehcache

ehcache简介

MyBatis整合ehcache

添加ehcache依赖

<!-- ehcache依赖 -->
	<dependency>
	    <groupId>org.mybatis.caches</groupId>
	    <artifactId>mybatis-ehcache</artifactId>
	    <version>1.1.0</version>
	</dependency>

配置Ehcache

在src/main/resources目录下新增ehcache.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:noNamespaceSchemaLocation="ehcache.xsd" updateCheck="true"
	monitoring="autodetect" dynamicConfig="true">
	
	<!-- 指定数据在磁盘中的存储位置 -->
	<diskStore path="D:\DEV_ENV\ehcache" /> 
	
	<!-- 缓存策略  -->
	<defaultCache 
		maxElementsInMemory="1000" 
		maxElementsOnDisk="10000000" 
		eternal="false"  
		overflowToDisk="false" 
		timeToIdleSeconds="120" 
		timeToLiveSeconds="120"
		diskExpiryThreadIntervalSeconds="120" 
		memoryStoreEvictionPolicy="LRU">
	</defaultCache>
</ehcache>

属性介绍:

maxElementsInMemory:内存中最大缓存对象数
maxElementsOnDisk:硬盘中最大缓存对象数,若是0表示无穷大
eternal:true表示对象永不过期,此时会忽略timeToIdleSeconds和timeToLiveSeconds属性,默认为false


overflowToDisk:true表示当内存缓存的对象数目达到了
diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认为120秒
timeToIdleSeconds: 设定允许对象处于空闲状态的最长时间,以秒为单位。当对象自从最近一次被访问后,如果处于空闲状态的时间超过了timeToIdleSeconds属性 值,这个对象就会过期,EHCache将把它从缓存中清空。只有当eternal属性为false,该属性才有效。如果该属性值为0,则表示对象可以无限 期地处于空闲状态


timeToLiveSeconds:设定对象允许存在于缓存中的最长时间,以秒为单位。当对象自从被存放到缓存中后,如果处于缓存中的时间超过了 timeToLiveSeconds属性值,这个对象就会过期,EhCache将把它从缓存中清除。只有当eternal属性为false,该属性才有 效。如果该属性值为0,则表示对象可以无限期地存在于缓存中。timeToLiveSeconds必须大于timeToIdleSeconds属性,才有意义。


memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。可选策略有:LRU(最近最少使用,默认策略)、FIFO(先进先出)、LFU(最少访问次数)。

修改XxxMapper.xml文件 

替代XxxMapper.xml里面的二级缓存开关标签

<!-- ehcache配置项 -->
	<cache type="org.mybatis.caches.ehcache.LoggingEhcache" > 
	    <property name="timeToIdleSeconds" value="3600"/><!--1 hour-->
	    <property name="timeToLiveSeconds" value="3600"/><!--1 hour-->
	    <property name="maxEntriesLocalHeap" value="1000"/>
	    <property name="maxEntriesLocalDisk" value="10000000"/>
	    <property name="memoryStoreEvictionPolicy" value="LRU"/>
	</cache>

有部分属性在ehcache.xml里面配置过,则mapper文件中的属性会覆盖掉ehcache.xml里面的属性值。同样,也可以使用一种偷懒的方式,直接使用一行,这里其余的属性则都使用ehcache.xml里面的默认属性了。

	<!-- ehcache配置项 -->
	<cache type="org.mybatis.caches.ehcache.LoggingEhcache" />

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值