Mybatis - 二级缓存
介绍
Mybatis 的二级缓存是 Application 级别的缓存,它可以提高对数据库查询的效率,以提高应用的性能。
读取缓存数据
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();
UserMapper userMapper = session.getMapper(UserMapper.class);
User user = userMapper.findUserById(2);
System.out.println(user);
session.close();
}
}
DefaultSqlSession selectOne 方法
public T selectOne(String statement, Object parameter) {
// 调用 selectList 方法
List list = this.selectList(statement, parameter);
if (list.size() == 1) {
return list.get(0);
}
}
DefaultSqlSession selectList 方法
public List selectList(String statement, Object parameter) {
// 调用重载方法
return this.selectList(statement, parameter, RowBounds.DEFAULT);
}
public List selectList(String statement, Object parameter, RowBounds rowBounds) {
MappedStatement ms = configuration.getMappedStatement(statement);
// 执行器查询
return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
}
}
CachingExecutor query 方法
private TransactionalCacheManager tcm = new TransactionalCacheManager();
public List query(MappedStatement ms, Object parameterObject, RowBounds rowBounds,
ResultHandler resultHandler) throws SQLException {
BoundSql boundSql = ms.getBoundSql(parameterObject);
CacheKey key = createCacheKey(ms, parameterObject, rowBounds, boundSql);
// 调用重载方法
return query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
}
@Override
public List query(MappedStatement ms, Object parameterObject, RowBounds rowBounds,
ResultHandler resultHandler, CacheKey key, BoundSql boundSql)throws SQLException {
Cache cache = ms.getCache();
if (cache != null) {
flushCacheIfRequired(ms);
if (ms.isUseCache() && resultHandler == null) {
ensureNoOutParams(ms, parameterObject, boundSql);
@SuppressWarnings("unchecked")
// 查找二级缓存
List list = (List) tcm.getObject(cache, key);
if (list == null) {
list = delegate. query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
// 缓存数据
tcm.putObject(cache, key, list);
}
return list;
}
}
return delegate. query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
}
TransactionalCacheManager getObject 方法
private Map transactionalCaches = new HashMap();
public Object getObject(Cache cache, CacheKey key) {
return getTransactionalCache(cache).getObject(key);
}
private TransactionalCache getTransactionalCache(Cache cache) {
TransactionalCache txCache = transactionalCaches.get(cache);
if (txCache == null) {
txCache = new TransactionalCache(cache);
transactionalCaches.put(cache, txCache);
}
return txCache;
}
TransactionalCache getObject 方法
// 上面方法传入的 SynchronizedCache 对象
private Cache delegate;
public Object getObject(Object key) {
// 二级缓存中查找
Object object = delegate.getObject(key);
return object;
}
缓存数据
TransactionalCacheManager putObject 方法
public void putObject(Cache cache, CacheKey key, Object value) {
// 上面定义过
getTransactionalCache(cache).putObject(key, value);
}
TransactionalCache putObject 方法
private Map
提交操作写入缓存
DefaultSqlSession commit 方法
@Override
public void commit() {
commit(false);
}
@Override
public void commit(boolean force) {
try {
// 执行器提交
executor.commit(isCommitOrRollbackRequired(force));
dirty = false;
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error committing transaction. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}
CachingExecutor commit 方法
@Override
public void commit(boolean required) throws SQLException {
delegate.commit(required);
tcm.commit();
}
TransactionalCacheManager commit 方法
public void commit() {
for (TransactionalCache txCache : transactionalCaches.values()) {
txCache.commit();
}
}
TransactionalCache commit 方法
public void commit() {
if (clearOnCommit) {
delegate.clear();
}
// 刷新操作
flushPendingEntries();
reset();
}
private void flushPendingEntries() {
for (Map.Entry