万网注册的域名怎么建设网站,如何做网站广告,盘锦建设工程信息网站,免费网站制作 最好Mybatis中共有三级缓存#xff0c;其中一级缓存默认开启#xff0c;作用范围是在sqlSession对象#xff08;同一个会话#xff09;#xff0c;二级缓存需要手动配置开启#xff0c;作用范围是在sqlSessionFactory对象下的同一个namespace范围#xff08;所以二级缓存是可…Mybatis中共有三级缓存其中一级缓存默认开启作用范围是在sqlSession对象同一个会话二级缓存需要手动配置开启作用范围是在sqlSessionFactory对象下的同一个namespace范围所以二级缓存是可以多个会话共享的不过如果多表关联查询会失效。三级缓存不用太关注。
二级缓存配置
mybatis-config.xml全局配置不配置也可以默认true。setting namecacheEnabled valuetrue/在对应的mapper.xml中对 cache标签进行配置!-- eviction缓存的清除策略当缓存达到上限后会自动触发对应算法清除缓存
flushInterval清除缓存的时间间隔在指定时间会自动清理缓存单位为毫秒
size缓存存储大小指定保存对象的个数List集合也算一个对象一般不推荐将List集合放入缓存中因为List集合较为多变命中率较
readOnly是否为只读设置为true代表数据缓存只读每次从缓存取出的对象是对象本身执行效率较高设置为false代表读取的对象为缓存的副本每次取出的对象是不同的这种操作对数据较为安全 --
cache evictionLRU flushInterval60000 size1000/
!-- 还可以在select、update等标签中指定是否将结果放入缓存或执行后是否直接清除缓存--
!-- 使用useCashe将结果集放入缓存中 --
select idxxx resultTypexxx useCachetrueSELECT * FROM xx
/select
!-- 针对于某些情景下想要在插入完成后就清空缓存可以使用flushCache属性设置为true则会在SQL执行结束后立刻清空缓存 --
update idupdate parameterTypecom.mybatis.entity.Good flushCachetrueUPDATE xx SET aa #{aa}WHERE bb #{bb}
/updateCache
Cache cache包下的Cache接口约定了整个缓存的规范有不同的Cache的实现类来实现它完成不同的功能。看类中方法可发现其实就是相当于对一个map的存取。
package org.apache.ibatis.cache;import java.util.concurrent.locks.ReadWriteLock;/*** 缓存*/
public interface Cache {/*** 该缓存对象的id*/String getId();/*** 向缓存中添加数据key是CacheKeyvalue是查询结果*/void putObject(Object key, Object value);/*** 根据指定的key在缓存中查找对应的结果对象**/Object getObject(Object key);/*** 删除key对应的缓存项**/Object removeObject(Object key);/*** 清空缓存*/void clear();/*** 缓存项的个数**/int getSize();/*** 获取读写锁*/default ReadWriteLock getReadWriteLock() {return null;}
}在调用Configuration的无参构造时同样会对常见的Cache对象的Alias别名做映射处理。 public Configuration() {typeAliasRegistry.registerAlias(PERPETUAL, PerpetualCache.class);typeAliasRegistry.registerAlias(FIFO, FifoCache.class);typeAliasRegistry.registerAlias(LRU, LruCache.class);typeAliasRegistry.registerAlias(SOFT, SoftCache.class);typeAliasRegistry.registerAlias(WEAK, WeakCache.class);}接下来就根据Configuration映射的顺序来逐一查看对应的缓存类。
PerpetualCache PerpetualCache类代表永久缓存用HashMap来实现对缓存的存储。
/**** 永久缓存* 一旦存入就一直保持** author Clinton Begin*/
public class PerpetualCache implements Cache {// Cache对象的唯一标识private final String id;// 记录缓存想的map对象private final MapObject, Object cache new HashMap();public PerpetualCache(String id) {this.id id;}Overridepublic String getId() {return id;}Overridepublic int getSize() {return cache.size();}Overridepublic void putObject(Object key, Object value) {cache.put(key, value);}Overridepublic Object getObject(Object key) {return cache.get(key);}Overridepublic Object removeObject(Object key) {return cache.remove(key);}Overridepublic void clear() {cache.clear();}Overridepublic boolean equals(Object o) {// 只要id相等就认为两个cache相同if (getId() null) {throw new CacheException(Cache instances require an ID.);}if (this o) {return true;}if (!(o instanceof Cache)) {return false;}Cache otherCache (Cache) o;return getId().equals(otherCache.getId());}Overridepublic int hashCode() {if (getId() null) {throw new CacheException(Cache instances require an ID.);}return getId().hashCode();}
}除了上面的PerpetualCache其余四个类都在org.apache.ibatis.cache.decorators包下使用到了装饰者模式。
FifoCache 底层为了了一个LinkedList链表来记录了cache的先后顺序每次从后添加如果size 1024则从头先remove 默认LinkedList大小为1024。除此之外还是使用装饰者模式调用其他的Cache对象来完成Cache的存储。
/*** FIFO缓存* 这个类就是维护一个FIFO链表其他都委托给所包装的cache去做。典型的装饰模式** FIFO (first in, first out) cache decorator.**/
public class FifoCache implements Cache {// 底层被装饰的底层Cache对象private final Cache delegate;// 用于记录key进入缓存的先后顺序private final DequeObject keyList;// 记录了缓存项的上限超过该值则需要清理最老的缓存项private int size;public FifoCache(Cache delegate) {this.delegate delegate;this.keyList new LinkedList();this.size 1024;}Overridepublic String getId() {return delegate.getId();}Overridepublic int getSize() {return delegate.getSize();}public void setSize(int size) {this.size size;}Overridepublic void putObject(Object key, Object value) {// 检测并清理缓存cycleKeyList(key);// 添加缓存项delegate.putObject(key, value);}Overridepublic Object getObject(Object key) {return delegate.getObject(key);}Overridepublic Object removeObject(Object key) {return delegate.removeObject(key);}Overridepublic void clear() {delegate.clear();keyList.clear();}private void cycleKeyList(Object key) {// 记录keykeyList.addLast(key);// 如果缓存达到上限则清理最老的缓存项if (keyList.size() size) {Object oldestKey keyList.removeFirst();delegate.removeObject(oldestKey);}}
}LruCache 和FifoCache的区别在于它使用了LinkedHashMap来记录着Cache的顺序在进行过期策略时删除最少使用的Cache。
/*** 最近最少使用缓存* 基于 LinkedHashMap 覆盖其 removeEldestEntry 方法实现。** Lru (least recently used) cache decorator.** author Clinton Begin*/
public class LruCache implements Cache {// 被装饰的底层cache对象private final Cache delegate;// 有序的hashmap用于记录key最近的使用情况private MapObject, Object keyMap;// 记录最少被使用的缓存项的keyprivate Object eldestKey;public LruCache(Cache delegate) {this.delegate delegate;setSize(1024);}Overridepublic String getId() {return delegate.getId();}Overridepublic int getSize() {return delegate.getSize();}public void setSize(final int size) {// 重新设置缓存大小时会重置keyMap字段注意LinkedHashMap构造函数的第三个参数true表示该LinkedHashMap记录的顺序是access-orderkeyMap new LinkedHashMapObject, Object(size, .75F, true) {private static final long serialVersionUID 4267176411845948333L;// 当调用LinkedHashMap.put方法会调用此方法Overrideprotected boolean removeEldestEntry(Map.EntryObject, Object eldest) {boolean tooBig size() size;// 如果已达到缓存上线则更新eldestKey字段后面会删除该项if (tooBig) {// 把eldestKey存入实例变量eldestKey eldest.getKey();}return tooBig;}};}Overridepublic void putObject(Object key, Object value) {// 添加缓存项delegate.putObject(key, value);// 删除最久未使用的缓存项cycleKeyList(key);}Overridepublic Object getObject(Object key) {// 修改LinkedHashMap中记录的顺序keyMap.get(key); // touchreturn delegate.getObject(key);}Overridepublic Object removeObject(Object key) {return delegate.removeObject(key);}Overridepublic void clear() {delegate.clear();keyMap.clear();}private void cycleKeyList(Object key) {keyMap.put(key, key);// eldestKey不为空表示已经达到缓存上限if (eldestKey ! null) {// 删除最久未使用的缓存项delegate.removeObject(eldestKey);eldestKey null;}}
}SoftCache JVM中对象的引用关系分为强、软、弱、虚。每种引用关系在JVM进行垃圾回收时回收的标准是不同的Mybatis的SoftCache其本质就是软引用。
public class SoftCache implements Cache {// 在SoftCache中最近使用的一部分缓存项不会被GC回收这就是通过将其value添加到hardLinksToAvoidGarbageCollection集合中实现的private final DequeObject hardLinksToAvoidGarbageCollection;// 引用队列用于记录已经被GC回收的缓存项对应的SoftEntry对象private final ReferenceQueueObject queueOfGarbageCollectedEntries;// 底层被装饰的底层Cache对象private final Cache delegate;// 强连接的个数默认是256private int numberOfHardLinks;public SoftCache(Cache delegate) {this.delegate delegate;//默认链表可以存256元素this.numberOfHardLinks 256;this.hardLinksToAvoidGarbageCollection new LinkedList();this.queueOfGarbageCollectedEntries new ReferenceQueue();}Overridepublic String getId() {return delegate.getId();}Overridepublic int getSize() {removeGarbageCollectedItems();return delegate.getSize();}public void setSize(int size) {this.numberOfHardLinks size;}Overridepublic void putObject(Object key, Object value) {// 清除已经被GC回收的缓存项removeGarbageCollectedItems();// 向缓存中添加缓存项delegate.putObject(key, new SoftEntry(key, value, queueOfGarbageCollectedEntries));}Overridepublic Object getObject(Object key) {Object result null;SuppressWarnings(unchecked) // assumed delegate cache is totally managed by this cache// 从缓存中查找对应的缓存项SoftReferenceObject softReference (SoftReferenceObject) delegate.getObject(key);// 检测缓存中是否有对应的缓存项if (softReference ! null) {// 获取SoftReference引用的valueresult softReference.get();// 已经被GC回收if (result null) {// 从缓存中清除对应的缓存项delegate.removeObject(key);// 未被GC回收} else {// See #586 (and #335) modifications need more than a read locksynchronized (hardLinksToAvoidGarbageCollection) {// 缓存项的value添加到hardLinksToAvoidGarbageCollection集合中保存hardLinksToAvoidGarbageCollection.addFirst(result);if (hardLinksToAvoidGarbageCollection.size() numberOfHardLinks) {// 超过numberOfHardLinks将最老的缓存项从hardLinksToAvoidGarbageCollection集合中清除hardLinksToAvoidGarbageCollection.removeLast();}}}}return result;}Overridepublic Object removeObject(Object key) {removeGarbageCollectedItems();return delegate.removeObject(key);}Overridepublic void clear() {synchronized (hardLinksToAvoidGarbageCollection) {// 清理强引用集合hardLinksToAvoidGarbageCollection.clear();}// 清理被GC回收的缓存项removeGarbageCollectedItems();// 清除底层delegate缓存中的缓存项delegate.clear();}private void removeGarbageCollectedItems() {SoftEntry sv;// 遍历queueOfGarbageCollectedEntries集合while ((sv (SoftEntry) queueOfGarbageCollectedEntries.poll()) ! null) {// 将已经被GC回收的value对象对应的缓存项清除delegate.removeObject(sv.key);}}private static class SoftEntry extends SoftReferenceObject {private final Object key;SoftEntry(Object key, Object value, ReferenceQueueObject garbageCollectionQueue) {// 指向value的引用是软引用且关联了引用队列super(value, garbageCollectionQueue);// 强引用this.key key;}}
}WeakCache WeakCache同SoftCache
/*** 弱引用缓存可以看到代码和SoftCache如出一辙就是SoftReference变成了WeakReference** Weak Reference cache decorator.* Thanks to Dr. Heinz Kabutz for his guidance here.** author Clinton Begin*/
public class WeakCache implements Cache {private final DequeObject hardLinksToAvoidGarbageCollection;private final ReferenceQueueObject queueOfGarbageCollectedEntries;private final Cache delegate;private int numberOfHardLinks;public WeakCache(Cache delegate) {this.delegate delegate;this.numberOfHardLinks 256;this.hardLinksToAvoidGarbageCollection new LinkedList();this.queueOfGarbageCollectedEntries new ReferenceQueue();}Overridepublic String getId() {return delegate.getId();}Overridepublic int getSize() {removeGarbageCollectedItems();return delegate.getSize();}public void setSize(int size) {this.numberOfHardLinks size;}Overridepublic void putObject(Object key, Object value) {removeGarbageCollectedItems();delegate.putObject(key, new WeakEntry(key, value, queueOfGarbageCollectedEntries));}Overridepublic Object getObject(Object key) {Object result null;SuppressWarnings(unchecked) // assumed delegate cache is totally managed by this cacheWeakReferenceObject weakReference (WeakReferenceObject) delegate.getObject(key);if (weakReference ! null) {result weakReference.get();if (result null) {delegate.removeObject(key);} else {synchronized (hardLinksToAvoidGarbageCollection) {hardLinksToAvoidGarbageCollection.addFirst(result);if (hardLinksToAvoidGarbageCollection.size() numberOfHardLinks) {hardLinksToAvoidGarbageCollection.removeLast();}}}}return result;}Overridepublic Object removeObject(Object key) {removeGarbageCollectedItems();return delegate.removeObject(key);}Overridepublic void clear() {synchronized (hardLinksToAvoidGarbageCollection) {hardLinksToAvoidGarbageCollection.clear();}removeGarbageCollectedItems();delegate.clear();}private void removeGarbageCollectedItems() {WeakEntry sv;while ((sv (WeakEntry) queueOfGarbageCollectedEntries.poll()) ! null) {delegate.removeObject(sv.key);}}private static class WeakEntry extends WeakReferenceObject {private final Object key;private WeakEntry(Object key, Object value, ReferenceQueueObject garbageCollectionQueue) {super(value, garbageCollectionQueue);this.key key;}}
}