问题

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。所以读到了缓存。

讨论Spring整合Mybatis时一级缓存失效得问题的更多相关文章

  1. spring管理hibernate,mybatis,一级缓存失效原因

    mybatis缓存:一级缓存和二级缓存 hibernate缓存:一级缓存和二级缓存 关于缓存: 缓存是介于物理数据源与应用程序之间,是对数据库中的数据复制一份临时放在内存中的容器, 其作用是为了减少应 ...

  2. 简单探讨spring整合mybatis时sqlSession不需要释放关闭的问题

    https://blog.csdn.net/RicardoDing/article/details/79899686 近期,在使用spring和mybatis框架编写代码时,sqlSession不需要 ...

  3. spring整合mybatis后,mybatis一级缓存失效的原因

    一般来说,可以在5个方面进行缓存的设计: 最底层可以配置的是数据库自带的query cache, mybatis的一级缓存,默认情况下都处于开启状态,只能使用自带的PerpetualCache,无法配 ...

  4. 分析下为什么spring 整合mybatis后为啥用不上session缓存

    因为一直用spring整合了mybatis,所以很少用到mybatis的session缓存. 习惯是本地缓存自己用map写或者引入第三方的本地缓存框架ehcache,Guava 所以提出来纠结下 实验 ...

  5. 2017年2月16日 分析下为什么spring 整合mybatis后为啥用不上session缓存

    因为一直用spring整合了mybatis,所以很少用到mybatis的session缓存. 习惯是本地缓存自己用map写或者引入第三方的本地缓存框架ehcache,Guava 所以提出来纠结下 实验 ...

  6. Spring Boot 整合mybatis时遇到的mapper接口不能注入的问题

    现实情况是这样的,因为在练习spring boot整合mybatis,所以自己新建了个项目做测试,可是在idea里面mapper接口注入报错,后来百度查询了下,把idea的注入等级设置为了warnin ...

  7. MyBatis之一级缓存及其一级缓存失效

    定义: 一级缓存:本地缓存:与数据库同一次会话(sqlSession)期间查询到的数据会放在本地缓存中,如果以后要获取相同的数据直接从缓存中获取,不会再次向数据库查询数据一个SqlSession拥有一 ...

  8. Mybatis之一级缓存(七)

    1. 介绍 Mybatis缓存分为一级缓存和二级缓存,在本节中我们介绍下一级缓存的使用及其特性 MyBatis的一级缓存是在一个Session域内有效的,当Session关闭后,缓存内容也随之销毁.缓 ...

  9. 深入源码理解Spring整合MyBatis原理

    写在前面 聊一聊MyBatis的核心概念.Spring相关的核心内容,主要结合源码理解Spring是如何整合MyBatis的.(结合右侧目录了解吧) MyBatis相关核心概念粗略回顾 SqlSess ...

随机推荐

  1. [Linux] 011 其它权限管理命令

    1. 权限管理命令:chown 命令名称:chown 命令英文原意:change file ownership 命令所在路径:/bin/chown 执行权限:所有用户 语法:chown [用户] [文 ...

  2. Dubbo的详解

    1.Dubbo是什么? Dubbo是一个分布式服务框架,简言之:dubbo就是个服务框架,如果没有分布式的需求,其实是不需要用的,只有在分布式的时候,才有dubbo这样的分布式服务框架的需求,并且本质 ...

  3. telnet访问出现telnet:Unable to connect to remote host: No route to host

    Linux下的防火墙默认是不允许telnet服务通过的,所以,当防火墙不允许telnet服务通过时就会出现上面的这种情况,可以将防火墙关闭或者勾选允许telnet服务即可解决如上的问题.

  4. tomcat内存使用情况

    预发布阿里云服务器的容器 tomcat会自己无缘无故重启,故引出一些查看tomcat内存使用情况观察的细枝末节: 1️⃣当前端口号进程信息和GC使用情况(1)显示端口的PID:lsof -i:端口示例 ...

  5. 【JAVA】java中的length和length()

    参考链接: 你注意到Java中的length和length()了吗?外加一个size() java中的求长度length有时有小括号,有时没有小括号,到底什么时候该加小括号呢? 总结: Java中St ...

  6. ToolStripComboBox 绑定数据

    //添加ComboBox tcbbQueryCondition.ComboBox.DataSource = RelationalOperators.GetAllOperators(); tcbbQue ...

  7. ASE Alpha Sprint - backend scrum 10

    本次scrum于2019.11.15在sky garden进行,持续30分钟 参与人: Xin Kang, Zhikai Chen, Jia Ning, Hao Wang 请假: Lihao Ran, ...

  8. hdu1257最少拦截系统 贪心

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1257 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽 然它的第 ...

  9. Android listview子控件的的点击事件(转)

    1.先看图,是否是你想要的 2.布局文件<?xml version="1.0" encoding="utf-8"?><LinearLayout ...

  10. 【LeetCode】BFS(共43题)

    [101]Symmetric Tree 判断一棵树是不是对称. 题解:直接递归判断了,感觉和bfs没有什么强联系,当然如果你一定要用queue改写的话,勉强也能算bfs. // 这个题目的重点是 比较 ...