Mybatis的一级缓存和二级缓存
基本介绍
- 程序在执行的时候,它调用的对象存在于内存中,而我们为了提高性能方便快速调用,把已经被调用过的对象存在于缓存中,再次调用相同的程序或者相同的对象的时候,不必去数据库或者其他的持久化设备中查询。
- 而Mybatis的缓存都是为了更好的执行查询语句,一旦执行增删改语句,缓存就会被清零
一级缓存
-
一级缓存的作用域是我们一个SqlSession对象,同一个SqlSession中执行相同的查询语句(查询的参数也相同),第一次查询获取结果的时候,就会把它也写入缓存中,那木第二次查询的时候就会直接在缓存中获取结果,而不会在数据库中获取。
-
它是基于PerpetualCache的本地缓存,基于HashMap实现。
public class PerpetualCache implements Cache { private final String id; // 缓存id private final Map<Object, Object> cache = new HashMap(); // 缓存的数据结构 public PerpetualCache(String id) { this.id = id; } public String getId() { return this.id; } public int getSize() { return this.cache.size(); } public void putObject(Object key, Object value) { this.cache.put(key, value); } public Object getObject(Object key) { return this.cache.get(key); } public Object removeObject(Object key) { return this.cache.remove(key); } public void clear() { //清除缓存 this.cache.clear(); } public boolean equals(Object o) { if (this.getId() == null) { throw new CacheException("Cache instances require an ID."); } else if (this == o) { return true; } else if (!(o instanceof Cache)) { return false; } else { Cache otherCache = (Cache)o; return this.getId().equals(otherCache.getId()); } } public int hashCode() { if (this.getId() == null) { throw new CacheException("Cache instances require an ID."); } else { return this.getId().hashCode(); } } }
-
在Mybatis中我们只要创建一个SqlSession对象,就会默认开启一个一级缓存。
-
缓存失效:我们执行完增删改语句之后,缓存就会失效。或者执行SqlSession的commit()和close()方法的时候也会清空一级缓存。
二级缓存
-
二级缓存是mapper级别的也可以说是namespace级别的。当我们多个SqlSession去执行去操作同一个mapper下的sql语句,他们是共用这个二级缓存的。
<mappers> <mapper resource="mapper/VideoMapper.xml"/> <mapper resource="mapper/VideoOrderMapper.xml"/> </mappers>
-
它也是基于PerpetualCache 的 HashMap本地缓存,可自定义存储源,如 Ehcache/Redis等
-
二级缓存是要我们去打开的
-
第一步 全局配置中加入cacheEnabled 并且将值设为true。
<settings> <setting name="cacheEnabled" value="true" /> </settings>
-
第二步开启 namespace下的二级缓存
-
<cache eviction="LRU" flushInterval="100000" readOnly="true" size="1024"/>
-
eviction : 就是我们的缓存的回收策略
常见的有两种 : LRU和FIFO
LRU: 最近最少使用,缓存不够的时候就会清除掉最长时间没有使用的数据
FIFO:先进先出,按数据的的进入缓存的顺序来清除它们
-
flushInterval:清空缓存的时间间隔,单位是ms
-
readOnly:只可以从缓存中读取数据。默认是false,我们要改为true
-
用来指定缓存中最多指定key的数量。(底层是HashMap)
-
-
-
二级缓存是跨sqlSessionz,只要它执行的是这个mapper中的查询语句,被查询到数据就会被存储于二级缓存中。
-
失效策略 :执行完增删改语句之后就会清空二级缓存
-
一级缓存和二级缓存的使用顺序: 优先二级缓存 —> 一级缓存 ----> 数据库
-
二级缓存的使用原则
- 二级缓存的中的数据是基于namespace的,不同的namespace下的缓存数据是互不干扰的,如果在多个namespace下对同一个表进行操作,那木缓存下的数据可能就会出现不一致的问题
- 查询多于修改时使用二级缓存 。