mybatis源码解析–mapper解析之cache
cache用法
MyBatis 包含一个非常强大的查询缓存特性,它可以非常方便地配置和定制。MyBatis 3 中的缓存实现的很多改进都已经实现了,使得它更加强大而且易于配置。
默认情况下是没有开启缓存的,除了局部的 session 缓存,可以增强变现而且处理循环 依赖也是必须的。要开启二级缓存,需要我们在自己的maper文件中添加
<cache type="" eviction="FIFO" flushInterval="60000" size="512" readOnly="" blocking="">
<property name="" value=""/>
</cache>
#type
表示自定义的缓存的类,没有的情况下会存在一个默认的缓存类PerpetualCache.class。
自定义的缓存类需要有一个以String为参数的构造函数
#eviction
表示缓存的策略(只支持默认的缓存类,自定义的缓存类不支持)
LRU – 最近最少使用的:移除最长时间不被使用的对象。
FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。
WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。
#flushInterval
(刷新间隔)可以被设置为任意的正整数,而且它们代表一个合理的毫秒 形式的时间段。
默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新
#size
(引用数目)可以被设置为任意正整数,要记住你缓存的对象数目和你运行环境的 可用内存资源数目。
默认值是 1024
#readOnly
(只读)属性可以被设置为 true 或 false。
只读的缓存会给所有调用者返回缓 存对象的相同实例。因此这些对象不能被修改。这提供了很重要的性能优势。可读写的缓存 会返回缓存对象的拷贝(通过序列化) 。
这会慢一些,但是安全,因此默认是 false
#blocking
是否采用阻塞的方式(加锁)
同时还需要我们在对应的SQL上面调整缓存的使用
<!--根据ID查询-->
<select id="selectById"
resultType="com.liubin.study.mybatis.object.dataobject.SupplierLabelDO"
useCache="true"
flushCache="false">
<include refid="selectFields"/>
<where>
label.id = #{id}
</where>
</select>
#useCache 是否使用缓存。
从缓存中读取,如果存在,那么直接返回。不存在,则查询数据库并更新缓存。
#flushCache 是否更新缓存
强制更新缓存
实现自定义的缓存
对于自定义的缓存,我们需要实现Cache接口,可以看一下Cache接口的内容
public interface Cache {
/**
* 返回缓存的唯一标识
*/
String getId();
/**
* 设置缓存
*/
void putObject(Object key, Object value);
/**
* 换取缓存
*/
Object getObject(Object key);
/**
* As of 3.3.0 this method is only called during a rollback
* for any previous value that was missing in the cache.
* This lets any blocking cache to release the lock that
* may have previously put on the key.
* A blocking cache puts a lock when a value is null
* and releases it when the value is back again.
* This way other threads will wait for the value to be
* available instead of hitting the database.
*
*
* @param key The key
* @return Not used
*/
Object removeObject(Object key);
/**
* 清空缓存
*/
void clear();
/**
* 可选的,获取缓存的数量
*/
int getSize();
/**
* 可选的,获取缓存的读写锁
*/
ReadWriteLock getReadWriteLock();
}
我们自行实现一个用mapper存储的缓存
/**
* 自定义实行的mybatis的缓存<br/>
*
* @Type
* @Desc
* @date 2018/8/2
* @Version
*/
public class SimpleCache implements Cache {
private final Logger LOGGER = LoggerFactory.getLogger(SimpleCache.class);
private String id;
private Map<Object, Object> cache = new HashMap<Object, Object>();
public SimpleCache(String id) {
this.id = id;
}
public String getId() {
return this.id;
}
public void putObject(Object key, Object value) {
LOGGER.info("putObject:{},{}",key,value);
cache.put(key,value);
}
public Object getObject(Object key) {
Object value = cache.get(key);
LOGGER.info("getObject:{},value:{}",key,value);
return value;
}
public Object removeObject(Object key) {
LOGGER.info("removeObject:{}",key);
return null;
}
public void clear() {
LOGGER.info("clear");
}
public int getSize() {
LOGGER.info("getSize");
return 0;
}
public ReadWriteLock getReadWriteLock() {
LOGGER.info("getReadWriteLock");
return null;
}
}
在Mapper.xml中使用自定义的缓存
<!--
自行实现的缓存缓存的配置
-->
<cache type="com.liubin.study.mybatis.cache.SimpleCache" eviction="FIFO" flushInterval="60000" size="512">
</cache>
<!--使用默认的缓存
<cache eviction="FIFO" flushInterval="60000" size="512">
</cache>-->
<!--根据ID查询-->
<sele