Mybatis-缓存

缓存原理

一级缓存(本地缓存)

  sqlSession级别的缓存(map)

工作机制

  与数据库同一次会话期间查询到的数据会放在本地缓存中,以后如果需要获取相同的数据,直接从缓存中拿,没必要再去查询数据库

一级缓存失效情况

  1. sqlSession不同;(多个sqlSession对象发出相同的查询请求,都会从数据库查询)
  2. sqlSession相同,查询条件不同;(都没查询过这个条件,当前缓存中肯定是没有啦,所以需要向数据库发出查询)
  3. sqlSession相同,两次查询之间执行了增删改操作;(做过增删改可能涉及脏数据,所以底层session.clear()清除了缓存)
  4. sqlSession相同,手动清除了一级缓存(session.clear()

二级缓存(全局缓存)

  基于namespace级别的缓存,一个namespace(mapper文件)对应一个二级缓存

工作机制

  1. 一个会话查询一条数据,这个数据就会被放在当前会话的一级缓存中
  2. 如果会话关闭,一级缓存中的数据会被保存到二级缓存中(只有会话提交或者关闭以后,一级缓存中的数据才会转移到二级缓存中)
  3. 新的会话查询信息,就可以参照二级缓存中的内容
  4. 不同namespace查出的数据会放在自己对应的缓存中(map)

使用二级缓存

  1. 开启全局二级缓存配置:<setting name="cacheEnabled" value="true"/>
  2. 在mapper.xml中配置<cache></cache>即可使用二级缓存
  3. 我们的POJO需要实现序列化接口,因为在二级缓存中为了数据安全,给用户的数据要经过序列化和反序列化的

和缓存有关的设置/属性

  • cacheEnabled=true;默认开启二级缓存
  • localCacheScope:本地缓存作用域,默认SESSION将当前会话的所有数据保存在会话缓存中;STATEMENT可以禁用一级缓存
  • 每个select标签都有useCache="true":如果设为false二级缓存不使用,一级缓存依然使用
  • 每个增删改标签都有flushCache="true":(一级二级缓存都会清除
  • sqlSession.clearCache();只是清除当前session的一级缓存

cache相关的属性

<cache eviction="FIFO" flushInterval="60000" readOnly="false" size="1024"></cache>
  • eviction:缓存的回收策略(默认的是 LRU):flushInterval:缓存刷新间隔(缓存多长时间清空一次,默认不清空,设置一个毫秒值)
    • LRU – 最近最少使用的:移除最长时间不被使用的对象。
    • FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
    • SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。
    • WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。
  • flushInterval:缓存刷新间隔(缓存多长时间清空一次,默认不清空,设置一个毫秒值)
  • readOnly:是否只读size:缓存存放多少元素;
    • true:只读;mybatis认为所有从缓存中获取数据的操作都是只读操作,不会修改数据;mybatis为了加快获取速度,直接就会将数据在缓存中的引用交给用户。不安全,速度快
    • false:非只读:mybatis觉得获取的数据可能会被修改;mybatis会利用序列化&反序列的技术克隆一份新的数据给你。安全,速度慢
  • type="":指定自定义缓存的全类名;实现Cache接口即可 

整合ehcache

  mybatis的cache只是用map来实现的,衍生考虑到会发生的问题:

  • 如果我们的应用一直开启是否存在内存溢出的问题?
  • 如果应用关了我们的二级缓存都没有了,下次开启用户访问查询则又要查询数据库
  • 如果我们只是想修改一条数据记录,但update则会把所属的namespace(或者说所有的,没测试)的所有缓存清空

所以有必要用缓存数据库来代替mybatis的二级缓存,我们只需要实现mybatis提供的cache接口即可

  1. 下载ehcache.jar及mybatis-ehcache适配包、slf4j-api.jar及slf4j-log4j的适配包
  2. 类路径下配置ehcache.xml
  3. mapper.xml中使用自定义缓存
<cache type="org.mybatis.caches.ehcache.EhcacheCache"></cache>

<!-- 引用缓存:namespace:指定和哪个名称空间下的缓存一样 -->
<cache-ref namespace="com.atguigu.mybatis.dao.EmployeeMapper"/>

  ehcache缓存的数据存放在本地磁盘中

原文地址:https://www.cnblogs.com/edda/p/13429659.html