mybatis 一级缓存源码分析

  • ​​使用场景​​
  • ​​源码分析​​
  • ​​清除缓存调用的情况​​
  • ​​调用update​​
  • ​​配置flushCache​​
  • ​​作用域设置为STATEMENT​​
  • ​​执行commit​​
  • ​​执行rollback​​
  • ​​sqlSession 调用clearCache()​​

使用场景

public static void main(String[] args) throws IOException {

String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);

SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();

/**
*一级缓存命中条件:
* 1.sql 和参数必须相同
* 2.必须是相同的statementId
* 3.sqlSession必须相同(会话级别的缓存)
* 4.RowBounds 返回行范围必须相同
*/
ActivityMapper mapper = sqlSession.getMapper(ActivityMapper.class);
ActivityEntity activity = mapper.getActivity(1);
//SqlSession sqlSession1 = sqlSessionFactory.openSession();
//ActivityMapper mapper1 = sqlSession1.getMapper(ActivityMapper.class);
/**
* 满足上面四个条件的前提条件下如何将缓存清除
* 1.sqlSession.clearCache();
* 2.未调用flushCache=true的查询
* 3。未执行update
*4。 缓存作用域不是STATEMENT——》将缓存作用域变小了,这种在子查询,嵌套查询中可以起作用
*/
sqlSession.clearCache();
ActivityEntity activity1 = mapper.getActivity(1);
System.out.println(activity==activity1);
}

mybatis 一级缓存源码分析_java

源码分析

mybatis 一级缓存源码分析_缓存_02


从上图可以看出来核心代码在query方法中,下面从query方法分析

org.apache.ibatis.executor.BaseExecutor#query

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--;
}

mybatis 一级缓存源码分析_java_03


以上6种数据组成了缓存key

org.apache.ibatis.executor.BaseExecutor#queryFromDatabase


List<E> list;
localCache.putObject(key, EXECUTION_PLACEHOLDER);
try {
//具体的Executor调用doQuery方法,查询数据库
list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);
} finally {
localCache.removeObject(key);
}
//填充到缓存中
localCache.putObject(key, list);
if (ms.getStatementType() == StatementType.CALLABLE) {
localOutputParameterCache.putObject(key, parameter);
}
return list;

清除缓存调用的情况

调用update

mybatis 一级缓存源码分析_数据库_04

配置flushCache

mybatis 一级缓存源码分析_数据库_05

作用域设置为STATEMENT

mybatis 一级缓存源码分析_java_06

执行commit

mybatis 一级缓存源码分析_java_07

执行rollback

mybatis 一级缓存源码分析_源码_08

sqlSession 调用clearCache()

mybatis 一级缓存源码分析_缓存_09