讨论Spring整合Mybatis时一级缓存失效得问题
问题
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时一级缓存失效得问题的更多相关文章
- spring管理hibernate,mybatis,一级缓存失效原因
mybatis缓存:一级缓存和二级缓存 hibernate缓存:一级缓存和二级缓存 关于缓存: 缓存是介于物理数据源与应用程序之间,是对数据库中的数据复制一份临时放在内存中的容器, 其作用是为了减少应 ...
- 简单探讨spring整合mybatis时sqlSession不需要释放关闭的问题
https://blog.csdn.net/RicardoDing/article/details/79899686 近期,在使用spring和mybatis框架编写代码时,sqlSession不需要 ...
- spring整合mybatis后,mybatis一级缓存失效的原因
一般来说,可以在5个方面进行缓存的设计: 最底层可以配置的是数据库自带的query cache, mybatis的一级缓存,默认情况下都处于开启状态,只能使用自带的PerpetualCache,无法配 ...
- 分析下为什么spring 整合mybatis后为啥用不上session缓存
因为一直用spring整合了mybatis,所以很少用到mybatis的session缓存. 习惯是本地缓存自己用map写或者引入第三方的本地缓存框架ehcache,Guava 所以提出来纠结下 实验 ...
- 2017年2月16日 分析下为什么spring 整合mybatis后为啥用不上session缓存
因为一直用spring整合了mybatis,所以很少用到mybatis的session缓存. 习惯是本地缓存自己用map写或者引入第三方的本地缓存框架ehcache,Guava 所以提出来纠结下 实验 ...
- Spring Boot 整合mybatis时遇到的mapper接口不能注入的问题
现实情况是这样的,因为在练习spring boot整合mybatis,所以自己新建了个项目做测试,可是在idea里面mapper接口注入报错,后来百度查询了下,把idea的注入等级设置为了warnin ...
- MyBatis之一级缓存及其一级缓存失效
定义: 一级缓存:本地缓存:与数据库同一次会话(sqlSession)期间查询到的数据会放在本地缓存中,如果以后要获取相同的数据直接从缓存中获取,不会再次向数据库查询数据一个SqlSession拥有一 ...
- Mybatis之一级缓存(七)
1. 介绍 Mybatis缓存分为一级缓存和二级缓存,在本节中我们介绍下一级缓存的使用及其特性 MyBatis的一级缓存是在一个Session域内有效的,当Session关闭后,缓存内容也随之销毁.缓 ...
- 深入源码理解Spring整合MyBatis原理
写在前面 聊一聊MyBatis的核心概念.Spring相关的核心内容,主要结合源码理解Spring是如何整合MyBatis的.(结合右侧目录了解吧) MyBatis相关核心概念粗略回顾 SqlSess ...
随机推荐
- python实现处理excel单元格中的数据
实现代码如下: # 将数据单元格(格式为:参数名=值)里的数据以键值对的形式放入字典中,返回该字典 class get_string: def cut_string(self,string): # 将 ...
- MySQL 查询语句--------------进阶7:子查询
#进阶7:子查询 /* 含义: 出现在其他语句中的select语句,称为子查询或者内查询 外部的查询语句,称为主查询或外查询 分类: 按照子查询出现的位置: select后面:只支持标量子查询 fro ...
- PHP_CodeIgniter _remap重新定义方法
如果controller定义了_remap方法, 在_remap中重新定义方法 class Test extends CI_Controller{ public function index(){ e ...
- PHP学习:set_time_limit,max_execution_time,sleep
set_time_limit 设置脚本最大允许执行时间,可以在php脚本中使用, 参数为秒,如果为0,表示无时间限制: set_time_limit(seconds); max_execution_t ...
- Spring学习(一)--简化Java开发,认识Spring
一.传统Java开发弊端 在传统的开发之中,任何一个有实际意义的应用都会由两个或更多的类所组成,这些类之间相互协调来完成特定的业务逻辑,按照传统的做法,每个对象负责管理与自己相互协作的对象(即他所依赖 ...
- SAS去空格
data test; x=" aaa bbb hahaha"; x1=compress(x); x2=left(x); p ...
- forEach究竟能不能改变数组的值
forEach究竟能不能改变数组的值 :https://blog.csdn.net/ZhengKehang/article/details/81281563 初学者每次提到Array对象的时候有些烦人 ...
- Codeforces 1105D (BFS)
题面 传送门 分析 考虑BFS while(棋盘没有满){ for 玩家 p{ 对p进行BFS,走s[p]步 } } 对于每个玩家p BFS的时候如果到了格子(x,y),就把\(vis[x][y]\) ...
- Pandas的基础使用
Pandas的数据结构 # 导入pandas与numpy import pandas as pd from pandas import Series, DataFrame import numpy a ...
- JS中去除字符串空白符
海纳百川,有容乃大 1.通过原型创建字符串的trim() //去除字符串两边的空白 String.prototype.trim=function(){ return this.replace(/(^\ ...