mybatis一级缓存
mybatis一级缓存:也叫做会话级缓存,生命周期仅存在于当前会话,不可以直接关关闭。但可以通过flushCache和localCacheScope对其做相应控制。
一级缓存源码
底层是map集合,其中的key是sql、statement等一共组成。value值就是查询的结果
public class PerpetualCache implements Cache {
private final String id;
private final Map<Object, Object> cache = new HashMap<>();
}
交给BaseMapper实现一级缓存,一级缓存是默认开启的,同一线程当中的缓存,是单线程的
public abstract class BaseExecutor implements Executor {
private static final Log log = LogFactory.getLog(BaseExecutor.class);
protected Transaction transaction;
protected Executor wrapper;
protected ConcurrentLinkedQueue<DeferredLoad> deferredLoads;
protected PerpetualCache localCache;
protected PerpetualCache localOutputParameterCache;
protected Configuration configuration;
protected int queryStack;
private boolean closed;
}
一级缓存的命中
1.sql和参数必须相同
2.必须是相同的statementID
3.sqlSession必须一样(会话级缓存)
4.RowBounds返回行范围必须相同(分页用的)
只有当以上情况完全相同,才会命中一级缓存。
一级缓存当中的访问
BaseExecutor -> query() 如果一级缓存中有,就访问一级缓存当中数据,就是key命中,如果没有命中一级缓存,就会调用queryFromDatabase(),接着调用doQuery()方法,查询数据库,填入缓存、
*注意 *:此时会使用创建的key创建一个缓存, CacheKey key = createCacheKey(ms, parameter, rowBounds, boundSql);根据信息创建key,调用doQuery()之后会将key,以及一个占位符放到缓存中,localCache.putObject(key, EXECUTION_PLACEHOLDER);此处是为了懒加载使用,后面我会单独写。
@Override
public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
BoundSql boundSql = ms.getBoundSql(parameter);
CacheKey key = createCacheKey(ms, parameter, rowBounds, boundSql);
return query(ms, parameter, rowBounds, resultHandler, key, boundSql);
}
@SuppressWarnings("unchecked")
@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())