介绍
Mybatis 默认开启一级缓存,一级缓存只是相对于同一个 SqlSession 而言。所以在参数完全一样的情况下,我们使用同一个 SqlSession 对象连续调用同一个 Mapper 方法,往往只执行一次SQL。
读取缓存数据
main 方法
public class Test {
public static void main(String[] args) throws Exception {
String resource = "SqlMapConfig.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession session = factory.openSession();
// 查询方法
Object obj = session.selectOne("com.dao.UserMapper.findUserById", 2);
System.out.println(obj.toString());
session.close();
}
}
DefaultSqlSession selectOne 方法
public <T> T selectOne(String statement, Object parameter) {
// 调用 selectList 方法
List<T> list = this.<T>selectList(statement, parameter);
if (list.size() == 1) {
return list.get(0);
}
}
DefaultSqlSession selectList 方法
public <E> List<E> selectList(String statement, Object parameter) {
// 调用重载方法
return this.selectList(statement, parameter, RowBounds.DEFAULT);
}
public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
MappedStatement ms = configuration.getMappedStatement(statement);
// 执行器查询
return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
}
}
BaseExecutor query 方法
// 一级缓存器
protected PerpetualCache localCache;
public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds,
ResultHandler resultHandler){
BoundSql boundSql = ms.getBoundSql(parameter);
CacheKey key = createCacheKey(ms, parameter, rowBounds, boundSql);
// 重载方法
return query(ms, parameter, rowBounds, resultHandler, key, boundSql);
}
public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds,
ResultHandler resultHandler, CacheKey key, BoundSql boundSql){
List<E> list;
// 一级缓存中取数据
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);
}
return list;
}
PerpetualCache getObject 方法
//一级缓存的本质就是一个 HashMap
private final Map<Object, Object> cache = new HashMap();
public Object getObject(Object key) {
return this.cache.get(key);
}
缓存数据
BaseExecutor queryFromDatabase 方法
private <E> List<E> queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds,
ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
List<E> list;
localCache.putObject(key, EXECUTION_PLACEHOLDER);
try {
list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);
} finally {
localCache.removeObject(key);
}
// 缓存数据
localCache.putObject(key, list);
return list;
}