Mybatis缓存

Mybatis缓存

​ Mybatis和hibernate一样都存在缓存机制,有了缓存查询的速度就提高了,这样就可以提高查询效率。

​ Myabtis中默认定义了两级缓存:一级缓存、二级缓存

两级缓存

​ ① 一级缓存是mybatis自动开启的,并且我们是没有办法关闭的,但是可以采用手动的方式进行清除(Sqlsession级别)

​ ② 二级缓存就是需要我们自己手动开启(全局),是基于namespace级别的缓存

一级缓存(Local Cache)

​ mybatis会在会话的Sqlsession对象建立缓存,将每次查询的结果缓存起来,当下次查询的时候,就会去判断有没有跟先前一样的查询,有的话就会直接从缓存中取出结果返回用户,不用再去跟数据库取查询数据。

​ mybatis在开启一个数据库会话时,会创建一个新的Sqlsession对象,对象中会有一个新的Executor对象,Executor对象中持有一个新的PerpetualCache对象,会话结束时,Sqlsession对象及其内部的Executor、PerpetualCache对象也会一起释放。

​ Sqlsession调用close()方法,释放一级缓存PerpetualCache对象,一级缓存就不可用。

​ SqlSession调用clearCache(),就会清空PerpetualCache()对象中的数据,但是对象还是可以使用。

​ SqlSession中执行CUD,就会清空PerpetualCache()对象的数据,但是对象还是可以使用。

缓存存在的条件:

​ 在同一个Sqlsession中,数据没有改变就不会刷新缓存。

缓存失效的条件:

​ ①并不是同一个Sqlsession对象

​ ②在查询时,查询条件不同

​ ③在查询的期间里进行CUD操作,没有R

​ ④在查询期间手动清除了缓存

session.clearCache();//手动清除缓存

缺点

​ ① 一级缓存不能会话共享,不同的会话对于相同的数据可能有一样的缓存。在多会话或者分布式下,会存在脏数据,要解决这个问题就要使用二级缓存;一级缓存没法关闭。

​ ② session级别缓存,在同一个Sqlsession中,同意的查询不再查询数据库,直接从缓存中取出。

​ ③ statement级别缓存,避免这个问题,可以将一级缓存的级别设置为statement级别,这样在每次查询之后就会清除一级缓存。

二级缓存

​ 在理解一级缓存的理解上,可以知道缓存堆集在Sqlsession类的实例对象上,但是有时候执行方法需要我们自己来写,在service中需要自己来构造方法,那每一次执行完毕之后,Sqlsession实例对象就会关闭,一级缓存就被清空了,这时候缓存是空的拿不到信息,就又要去执行service方法去拿到结果。

​ 二级缓存存储在Mapper实例中,多个Sqlsession对象加载同一个Mapper时,就共享了同一个Mapper缓存。只要哎Mapper和select中配置了缓存,mybatis就会优先从二级缓存中取,再是一级缓存。

​ Mybatis的查询数据的顺序是:

​ 二级缓存 —> 一级缓存 —> 数据库

当执行CUD的时候,Mapper实例的缓存又会被清空。

​ 二级缓存的作用范围更广,那么他肯定是在Sqlsession的外层,否则不可能被多个Sqlsession共享。

​ mybatis采用了一个装饰器类来维护——CachingExecutor。如果开启了二级缓存,Mybatis在创建Executor的对象的时候就会对Executor对象进行装饰。CachingExecutor对于查询会去判断有没有缓存结果,有就返回,没有就会委托给真正的查询器Executor实现类。

开启二级缓存的方法

​ 一、配置文件中: mybatis.configuration.cache-enable= true

​ 二、在Mapper.xml中添加**** 标签

<cache type="org.apache.ibatis.cache.impl.PerpetualCache"
    size="1024"
eviction="LRU"
flushInterval="120000"
readOnly="false"/>

eviction:缓存的回收策略:

LRU – 最近最少使用的:移除最长时间不被使用的对象。

FIFO – 先进先出:按对象进入缓存的顺序来移除它们。

SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。

WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。

默认的是 LRU。

flushInterval:缓存刷新间隔(任意正整数)

​ 缓存多长时间清空一次,默认不清空,设置一个毫秒值
readOnly:是否只读:
​ **true:**只读;mybatis认为所有从缓存中获取数据的操作都是只读操作,不会修改数据。
​ mybatis为了加快获取速度,直接就会将数据在缓存中的引用交给用户。不安全,速度快
​ **false:**非只读:mybatis觉得获取的数据可能会被修改。mybatis会利用序列化&反序列的技术克隆一份新的数据给你。安全,速度慢。
size: 引用数目,缓存对象的大小和运行环境中可用的内存资源,默认1024;
​ **type="":**指定自定义缓存的全类名:


​ 实现Cache接口即可;
blocking: 若缓存中找不到对应的key,是否会一直blocking,直到有对应的数据进入缓存。

​ 二级缓存是事务性的,Sqlsession完成并提交时,是完成并回滚。

​ 在Mapper.xml配置中配置了之后select会被缓存,CUD会刷新缓存。

​ 如果cacheEnable = true,但是Maper.xml中没有配置是不会有二级缓存的,但是还会出现CachingExecutor对象。

事务不提交,缓存是不会存在的。

​ 这个原因是由于二级缓存是使用了TransactionalCacheManager来管理,最后调用TransactionalCache的getObject()、putObject()、commit()方法,TransactionalCache里持有真正的Cache对象。在putObject()的时候,只是添加到entriesToAndOnCommit()里面,只有他的commit()方法调用时候才会去执行flushPendingEntries()写入实际缓存。

POJO是需要序列化的

只有一级缓存关闭的情况下二级缓存才会生效

外部缓存

EhCache

Redis

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值