MyBatis中的缓存机制

MyBatis中存在两种缓存机制:一级缓存、二级缓存。

一级缓存指的是MyBatis自带的基于SqlSession的缓存,自动生效,且无法关闭。

当我们创建一个SqlSession并通过它从数据库中查询到一条数据时,这条数据会放在该SqlSession的缓存区中。

如果使用同一个SqlSession再查询一次相同的内容,则直接从缓存区中返回数据。以此降低查数据库的次数。

如果遇到以下四种情况,一级缓存会失效(无法命中):
  • 1、查询的内容和结果完全相同,使用的不是同一个SqlSession
  • 2、使用的是同一个SqlSession,但是查询的条件不同(查询结果不同)
  • 3、同一个SqlSession,但是在两次查询之间执行了DML(增删改操作)
  • 4、手动调用clearCache()清理了缓存区

如果一级缓存无法满足我们的需求,则可以使用二级缓存。二级缓存是基于namespace的全局缓存(基于每一个Mapper映射接口)。

每个Mapper二级缓存都有自己的一个缓存区域(底层Map实现),当一级缓存所在的SqlSession被关闭时,数据就会进入到二级缓存中。

二级缓存使用步骤
1、核心文件中开启全局缓存设置
<setting name="cacheEnabled" value="true">
2、在mapper.xml中开启二级缓存
<cache></cache>
3、需要缓存的数据类型需要实现序列化接口
cache配置中的属性
  • eviction 配置缓存回收策略,可选值:

    • LRU (默认)最近最少使用的,移除最长时间不被使用的对象

    • FIFO 先进先出,按照对象进入缓存的顺序移除它们

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

      强引用:平时使用new关键字创建的对象都是强引用,例如:

      Student stu = new Student();
      ArrayList list = new ArrayList();
      

      强引用指的是只要有任何引用指向该对象,那么gc一定不会回收它。

      生命周期最长,存在感较强。

      软引用:如果内存空间不足,gc在开始工作的时候优先会回收软引用类型的对象。

      生命周期一般长,存在感一般强。

    • WEAK 弱引用,更积极地移除基于垃圾回收器状态和弱引用规则的对象

      生命周期最短。无论当前内存是否够用,只要gc工作就一定会将弱引用对象回收掉。

      public static void main(String[] args) {
              
              
      		// 软引用对象
      		Object obj = new Object();
      		SoftReference soft = new SoftReference(obj);
      		obj = null;
      		// 弱引用对象
      		Object obj2 = new Object();
      		WeakReference weak = new WeakReference(obj2);
      		obj2 = null;
      	}
      
  • flushInterval 缓存刷新间隔,单位为毫秒

    如果长时间不刷新缓存区,可能会导致缓存区中的数据和数据库中的不一致。

    刷新缓存区的意思就是把所有的缓存全部清除,下一次全部重新查询。

  • readOnly 设置是否“只读“,值为true或false

    • 如果设为true,则代表向MyBatis表明我们从缓存中取对象仅仅是为了读取属性,而不会修改

      MyBatis则会将缓存中对象的引用直接返回。

      注意:缓存中的数据如果被修改,则没有存在的意义。

      特点:速度快、不安全

    • 如果设为false,则代表向MyBatis表明我们取出对象之后可能会进行修改操作。

      为了保证缓存中的原数据不被修改(与数据库真实数据保持一致),MyBatis会将缓存中的对象通过序列化反序列化技术克隆一份并返回。

      特点:速度慢、安全

    • 业务主要以查询为主,可以设置readOnly="true"来增加查询的效率。

      如果拿到缓存中的对象之后,由于某些业务逻辑的需要,不得不修改它的一些属性值,

      则最好将readOnly设为false以确保数据的安全性、准确性。

  • size 缓存中最大对象数量,默认值为1024

  • type 指定自定义缓存

  • 如果mapper中某条select语句不希望使用缓存,而是强制到数据库中查询数据,则可以添加如下属性:

    <select id="findxxxxByxxxxx" useCache="false">
    
  • 默认情况下,每次执行完DML操作之后缓存都会失效,原因是<insert><delete><update>三种元素中存在一个默认的属性值用来配置是否刷新缓存。如果不希望DML之后缓存失效,将其设为false即可:

  • <delete id="xxxx" flushCache="false">
    

猜你喜欢

转载自blog.csdn.net/WziH_CSDN/article/details/108804559