流程图:
1、进入query方法
queryStack嵌套查询使用到的层级
@Override
public Object getObject(Object key) {
return cache.get(key);
}
private final Map<Object, Object> cache = new HashMap<>();
可以看到一级缓存底层就是一个hashmap作为缓存
缓存的key定义:
由6个部分组成:
1、statementId
2、分页条件:Integer的最小值0
3、分页条件:Interget的最大值2147483647
4、sql语句
5、参数
6、环境变量
第一次查询,缓存为null,那么就走doQuery查询数据库并填充缓存
第二次查询,直接获取缓存中的数据
验证上一节刷新缓存场景:mybatis源码-一级缓存命中的场景
1、update后会清空缓存
@Override
public int update(MappedStatement ms, Object parameter) throws SQLException {
ErrorContext.instance().resource(ms.getResource()).activity("executing an update").object(ms.getId());
if (closed) {
throw new ExecutorException("Executor was closed.");
}
clearLocalCache();
return doUpdate(ms, parameter);
}
2、配置flushCache=true会清空缓存
@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;
}
if (queryStack == 0 && ms.isFlushCacheRequired()) {
clearLocalCache();
}
这段代码表示:如果查询是第一次(不是子查询),并且配置了flushCache=true,那么清空缓存
3、配置localCacheScope=STATEMENT会清空缓存
if (queryStack == 0) {
for (DeferredLoad deferredLoad : deferredLoads) {
deferredLoad.load();
}
// issue #601
deferredLoads.clear();
if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {
// issue #482
clearLocalCache();
}
}
这段代码表示:如果查询是第一次(不是子查询),并且配置了localCacheScope=STATEMENT,那么清空缓存
4、commit、rollback操作会清空缓存
@Override
public void commit(boolean required) throws SQLException {
if (closed) {
throw new ExecutorException("Cannot commit, transaction is already closed");
}
clearLocalCache();
flushStatements();
if (required) {
transaction.commit();
}
}
@Override
public void rollback(boolean required) throws SQLException {
if (!closed) {
try {
clearLocalCache();
flushStatements(true);
} finally {
if (required) {
transaction.rollback();
}
}
}
}