### Mybatis中的缓存
#### 一级缓存
mybatis的一级缓存默认是不可关闭的,生命周期与SqlSession同步,在同一个SqlSession对象中,多次查询相同的Sql语句只会查询一次数据库,mybatis查询时会先去查询一级缓存,如果一级缓存不存在就会查询数据库,并将数据库查询出的数据放入一级缓存,一级缓存在PerpetualCache使用HashMap类型集合维护Key和对应的对象,key是使用CacheKey(statementId,分页参数,BoundSql)对象来维护的
##### 一级缓存的生命周期
Mybatis一级缓存的生命周期与SqlSession一致,但是在分布式环境下或者有多个SqlSession的情况下,数据库写会引起脏数据,SqlSession创建的时候会创建对应的缓存对象,在SqlSession执行了增删改方法时,会清空对应的一级缓存,或者执行SqlSession.clearCache()方法也可以清空缓存数据,此时还可以继续操作缓存对象,**使用SqlSession.close()方法时将会释放一级缓存,缓存对象不再可用**
##### 如何关闭一级缓存
根据源码来查看,一级缓存默认是开启的并且是不可关闭的,只有其中对应的方法进行配置ms.isFlushCacheRequired()为true可以每次执行对应查询方法时清空一级缓存,或者在配置文件中将对应的配置为
LocalCacheScope配置为(默认值是Session)LocalCacheScope.STATEMENT也可以达到相同的效果,每次都会清空缓存
```xml
<settings>
<!--自动清除一级缓存 -->
<setting name="localCacheScope" value="STATEMENT"/>
</settings>
```
```java
@Override
public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId());
if (closed) {
throw new ExecutorException("Executor was closed.");
}
if (queryStack == 0 && ms.isFlushCacheRequired()) {
clearLocalCache();
}
List<E> list;
try {
queryStack++;
list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;
if (list != null) {
handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);
} else {
list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
}
} finally {
queryStack--;
}
if (queryStack == 0) {
for (DeferredLoad deferredLoad : deferredLoads) {
deferredLoad.load();
}
// issue #601
deferredLoads.clear();
if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {
// issue #482
clearLocalCache();
}
}
return list;
}
```
#### 二级缓存
mybatis中的二级缓存逻辑与一级缓存类似,第一次查询时将数据序列化后放入缓存中,第二次查询时直接查询对应缓存并将数据反序列化取出,因为二级缓存是用序列化的方式实现的,**所以对应的实体需要实现Serializable接口**,一级缓存的作用范围是SqlSession的,二级缓存的作用范围是基于Mapper文件中的namespace的,多个Sqlsession可以共享mapper中的二级缓存区域,多个mapper如果namespace相同也可以共享二级缓存区域
##### 开启二级缓存
```xml
<!--开启二级缓存 -->
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
```
或者可以在具体的mapper文件中进行开启缓存
```xml
<cache></cache>
```
Mybatis学习笔记(三)-Mybatis中的缓存介绍