mybatis缓存

一级缓存

  • 这里写图片描述
  • mybatis的一级缓存是SQLSession级别的缓存,在操作数据库时需要构造SqlSession对象,在对象中有一个HashMap用于存储缓存数据,不同的SqlSession之间缓存数据区域(HashMap)是互相不影响的。
  • 一级缓存的作用域是SqlSession范围的,当在同一个SqlSession中执行两次相同的sql语句时,第一次执行完毕会将数据库中查询的数据写到缓存(内存)中,第二次查询时会从缓存中获取数据,不再去底层进行数据库查询,从而提高了查询效率。
  • ==如果SqlSession执行了DML操作(insert、update、delete),并执行commit()操作,mybatis则会清空SqlSession中的一级缓存,这样做的目的是为了保证缓存数据中存储的是最新的信息,避免出现脏读现象==
  • 当一个SqlSession结束后该SqlSession中的一级缓存也就不存在了,Mybatis默认开启一级缓存,不需要进行任何配置。

一级缓存的验证

  • 第一种方式:同一个代理类对象,两次执行相同的sql查询语句
    • 测试代码:这里写图片描述
    • 结果: 这里写图片描述
    • 总结:通过观察结果可以看出,在第一次查询id为1的Employee对象时执行了一条select语句,但是第二次获取id为1的Employee对象时并没有执行select语句,因为此时一级缓存也就是SqlSession缓存中已经缓存了id为1的Employee对象,Mybatis直接从缓存中将对象取出来,并没有再次去查询数据库,所以第二次也就没有执行select语句
  • 第二种方式:进行事务提交后,缓存清空:
    • 代码 这里写图片描述
    • 结果:这里写图片描述
    • 在第一次查询id为1的employee对象时执行了一条select语句,接下来执行了一个delete并commit操作,Mybatis为了保证缓存中存储的是最新消息,会清空SqlSession缓存。当第二次获取id为1的User对象时一级缓存也就是SqlSession缓存中并没有缓存任何对象,所以Mybatis再次执行语句去查询id为1的Exployee对象
  • 第三中方式:执行一次后,关闭sqlSession
    • 代码:这里写图片描述
    • 结果:这里写图片描述
    • 在第一次查询id为1的User对象时执行了一条select语句,接下来调用SqlSession的close()方法,该方法会关闭SqlSession缓存,当第二次获取id为1的Employee对象时一级缓存也就是SqlSession缓存是一个新的对象,其中并没有缓存任何对象,所以Mybatis再次执行select语句去查询id为1的Employee对象

二级缓存

  • 二级缓存是mapper级别的缓存,使用二级缓存时,多个SqlSession使用同一个Mapper的sql语句去操作数据库,得到的数据会存在二级缓存区域,它同样是使用HashMapper进行数据存储,相比一级缓存SqlSession,二级缓存的范围更大,多个SqlSession可以共用二级缓存,二级缓存是跨SqlSession的。
  • 二级缓存是多个SqlSession共享的,其作用域是mapper的同一个namespace,不同的SqlSession两次执行相同的namespace下的sql语句,且向sql中传递的参数也相同,即最终执行相同的sql语句,则第一次执行完毕会将数据库中查询的数据写到缓存(内存),第二次查询时会从缓存中获取数据,不再去底层数据库查询,从而提高查询效率。
  • ==Mybatis默认没有开启二级缓存,需要在setting全局参数中配置开启二级缓存。==
  • 禁用二级缓存

    • 在statement中设置userCache=false可以禁用当前的select语句的二级缓存,及每次查询都会发出sql区查询,默认值是true 这里写图片描述
    • 这样设置了的sqlstatement每次查询会不使用二级缓存
  • 新缓存(清空缓存)

    • 执行完事务提交的方法 后需要刷新缓存,设置flushcache=true表示刷新缓存,这样可以避免脏读

二级缓存开启

  • 第一步:在mybatis的全局配置文件中这里写图片描述
  • cacheEnabled的value为true表示在此配置文件下开启二级缓存,该属性默认为false。
  • 第二步:需要指定开启二级缓存的namepace的mapper,在mepper映射配置文件中开启这里写图片描述
  • cache元素用来开启当前mapper的namespace下的二级缓存,该元素的属性设置如下:
    • flushInterval:刷新间隔,可以被设置为任意的正整数,而且它们代表一个合理的毫秒形式的时间段,默认情况下是不设置的,也就是没有刷新间隔,缓存仅仅调用语句时刷新。
    • size:缓存数目,可以被设置为任意正整数,要缓存对象数目和运行环境可用内存资源数目,默认值是1024.
    • readOnly:只读属性可以被设置为true或false,只读的缓存会给所有调用者返回缓存对象的相同实例,因此这些对象不能被修改。这提供了很重要的性能优势,可读写的缓存会返回缓存对象的拷贝(通过序列化),这会慢一些,但是安全,因此默认是false。
    • eviction:收回策略,默认为LRU,有如下几种
      • LRU:最近最少使用的策略,移除最长时间不被使用的对象。
      • FIFO:先进先出策略,按对象进入缓存的顺序来移除它们。
      • SOFT:软引用策略,移除基于垃圾回收器状态和软引用规则的对象。
      • WEAK:弱引用策略,更积极地移除基于垃圾收集器状态和弱引用规则的对象。
  • ==注意:==
    • 使用二级缓存时,与查询结果映射的java对象必须实现java.io.Serializable接口的序列化和反序列化操作
    • 如果存在父类,其成员都需要实现序列化接口,
    • 实现序列化接口是为了对缓存数据进行序列化和反序列化操作,因为二级缓存数据存储介质多种多样,不一定在内存,有可能是硬盘或者远程服务器。

二级缓存测试

  • 代码:这里写图片描述
  • 结果:这里写图片描述
  • 分析:第一次查询是关闭了一级缓存,第二次查询从一级缓存中没有找到,就会从二级缓存中找,并且找到了,所以只有一条sql语句

二级缓存应用场景

  • 对于访问多的请求且用户对查询结果实时性要求不高,此时可以采用mybatis二级缓存技术降低数据库访问量,提高访问的速度,业务场景如:耗时较高的统计分析sql,电话账单查询sql
  • 实现方法如下:通过设置刷新的时间间隔,由mybatis每隔一段时间自动清空缓存,根据数据变化的频率设置刷新缓存的间隔flushinterval,比如设置为30分钟,60分钟,24小时等,根据需求而定

局限性

  • mybatis对细粒度缓存级别的缓存实现不好,比如;对商品信息进行缓存,由于商品信息查询访问量很大,但是要求用户每次都能查询最新的商品信息,此时如果使用mybatis的二级缓存,就无法实现当一个商品刷新的时候,只刷新该商品的缓存信息,不刷心其他商品的缓存信息,因为mybatis的二级缓存区域以mapper为单位划分,当一个商品的信息的变化,会将所有的商品的缓存数据全部清空,解决此类问题需要在业务层根据需求对数据有针对性的缓存
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值