问题

1、学习测试时发现了一级缓存并没有生效,先看案例:

setting配置:

  <settings>
<!-- (1) 提供可控制Mybatis框架运行行为的属性信息 -->
<setting name="lazyLoadingEnabled" value="false" />
<setting name="logImpl" value="STDOUT_LOGGING" />
<setting name="localCacheScope" value="SESSION"/>
</settings>

测试代码:

   @Test
public void test1(){
try(SqlSession sqlSession = sessionFactory.openSession();){
GoodsMapper goodsMapper = sqlSession.getMapper(GoodsMapper.class);
Goods goods = goodsMapper.getGoodsById(1,"电脑2");
Goods goods2 = goodsMapper.getGoodsById(1,"电脑2");
}
} @Autowired
private GoodsMapper goodsMapper; @Test
public void test2(){
Goods goods = goodsMapper.getGoodsById(1,"电脑2");
Goods goods2 = goodsMapper.getGoodsById(1,"电脑2");
}

问题分析

首先我们都知道一级缓存的作用范围有两种,一种是sqlSession,一种是STATEMENT。我们看test2方法,用的都是同一个mapper,按理说是应该只查询一次的啊,难道同一个mapper的sqlSession不一样。紧接着我试了test1方法,用的也都是同一个mapper,发现只查询了一次数据库。难道这两种方法有不一样的地方吗?

答案就在MapperProxy类当中,我们打断点执行test1方法,我们发现他的sqlSession类型是DefaultSqlSession

然后再执行test2方法,我们发现他的sqlSession类型是SqlSessionTemplate

他们的差别找到了,失效的原因多半就是SqlSessionTemplate造成的,SqlSessionTemplate类里有一个SqlSessionInterceptor,我们看他的invoke方法,代码如下:

private class SqlSessionInterceptor implements InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
SqlSession sqlSession = getSqlSession(
SqlSessionTemplate.this.sqlSessionFactory,
SqlSessionTemplate.this.executorType,
SqlSessionTemplate.this.exceptionTranslator);
try {
Object result = method.invoke(sqlSession, args);
if (!isSqlSessionTransactional(sqlSession, SqlSessionTemplate.this.sqlSessionFactory)) {
// force commit even on non-dirty sessions because some databases require
// a commit/rollback before calling close()
sqlSession.commit(true);
}
return result;
} catch (Throwable t) {
Throwable unwrapped = unwrapThrowable(t);
if (SqlSessionTemplate.this.exceptionTranslator != null && unwrapped instanceof PersistenceException) {
// release the connection to avoid a deadlock if the translator is no loaded. See issue #22
closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
sqlSession = null;
Throwable translated = SqlSessionTemplate.this.exceptionTranslator.translateExceptionIfPossible((PersistenceException) unwrapped);
if (translated != null) {
unwrapped = translated;
}
}
throw unwrapped;
} finally {
if (sqlSession != null) {
closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
}
}
}
}

此时我们发现sqlSession是通过invoke方法里的getSqlSession方法重新赋值了,而我打断点发现,同一个mapper调同样的方法获得的sqlSession是不一样的,既然不一样,那当然读不到缓存了。

而DefaultSqlSession则是直接执行查询方法,是同一个sqlSession。所以读到了缓存。

最新文章

  1. 背水一战 Windows 10 (11) - 资源: CustomResource, ResourceDictionary, 加载外部的 ResourceDictionary 文件
  2. [zz]Maya C++ API Programming Tips
  3. 探秘JavaScript中的六个字符
  4. ListBox mvvm 学习笔记
  5. ipython, 一个 python 的交互式 shell,比默认的python shell 好用得多,支持变量自动补全,自动缩进,支持 bash shell 命令,内置了许多很有用的功能和函数
  6. ntpdate server时出错原因及解决
  7. spoj 2148
  8. PAT_1040 有几个PAT
  9. python-Django环境搭建
  10. mysql explain 命令简解
  11. RESTful架构3--开发实战
  12. 知问前端——html+jq+jq_ui+ajax
  13. elasticsearch的映射(mapping)和分析(analysis)
  14. 简单的面向对象(OO)练习
  15. TensorFlow从1到2(七)线性回归模型预测汽车油耗以及训练过程优化
  16. DELPHI中MDI子窗口的关闭和打开
  17. 【译】第11节---数据注解-TimeStamp
  18. VS2010-自定义控件
  19. supervisor管理uwsgi
  20. Python3 isprintable() 方法

热门文章

  1. Java Web项目启动执行顺序
  2. poj3126Prime Path (BFS+素数筛)
  3. 基于K-means Clustering聚类算法对电商商户进行级别划分(含Octave仿真)
  4. 命令行下DEBIAN7时间错误的问题(转)
  5. Git011--分支管理策略
  6. mooc-IDEA 关联Spring&amp;DB --011
  7. SQL Server 分页语句查询
  8. javaweb的Filter过滤器设置全站编码
  9. [BZOJ1604][Usaco2008 Open]Cow Neighborhoods 奶牛的邻居 (Treap+单调队列)
  10. emacs配置&amp;博客界面源代码