博客
关于我
你凭什么说Spring会导致MyBatis的一级缓存失效
阅读量:342 次
发布时间:2019-03-04

本文共 1985 字,大约阅读时间需要 6 分钟。

Spring和MyBatis集成后,一级缓存失效的原因及解决方案

近年来,关于Spring和MyBatis集成后导致MyBatis的一级缓存失效的说法屡见不鲜。这一现象确实引起了开发者的诸多困惑和不满。为了弄清楚真相,我决定深入研究这一问题。

一、初步分析

首先,我编写了一个简单的测试代码,验证一级缓存是否正常工作。代码如下:

AnnotationConfigApplicationContext annotationConfigApplicationContext;@Beforepublic void init() {    annotationConfigApplicationContext = new AnnotationConfigApplicationContext(AppConfig.class);}@Testpublic void selectTest() {    TestMapper bean = annotationConfigApplicationContext.getBean(TestMapper.class);    List
users = bean.selectUser("周六"); System.out.println(users); List
users1 = bean.selectUser("周六"); System.out.println(users == users1);}

根据MyBatis的一级缓存规则,理论上这两次查询应命中缓存。但测试结果显示,两次查询都直接从数据库查询,缓存未命中。这表明Spring确实导致了MyBatis的一级缓存失效。

二、源码分析

为了找出原因,我决定查看源码。发现MyBatis在Spring集成后,SqlSession被替换成了SqlSessionTemplate。SqlSessionTemplate继承了SqlSession接口,并使用JDK动态代理实现。动态代理的InvocationHandler在处理每个方法调用时,获取了不同的SqlSession。这意味着每次查询使用的是不同的SqlSession,自然无法命中一级缓存。

进一步分析发现,SqlSessionTemplate的selectList方法调用了sqlSessionProxy的selectList,而sqlSessionProxy又是一个动态代理。每次调用都会创建新的SqlSession,这与MyBatis的一级缓存规则不符。

三、解决方案

为了验证这一点,我尝试在代码中添加事务管理。通过获取DataSourceTransactionManager并启动一个事务,确保两次查询使用同一个SqlSession。修改后的代码如下:

@Testpublic void selectTest() {    TestMapper bean = annotationConfigApplicationContext.getBean(TestMapper.class);    DataSourceTransactionManager dataSourceTransactionManager = annotationConfigApplicationContext.getBean(DataSourceTransactionManager.class);    TransactionStatus transaction = dataSourceTransactionManager.getTransaction(new DefaultTransactionDefinition());    List
users = bean.selectUser("周六"); System.out.println(users); List
users1 = bean.selectUser("周六"); System.out.println(users == users1); dataSourceTransactionManager.commit();}

此时,两次查询使用了同一个SqlSession,一级缓存成功命中。

四、总结

Spring和MyBatis集成后,一级缓存失效的原因是SqlSession被动态代理替换,导致每次查询使用不同的SqlSession。通过启用事务管理,确保使用同一个SqlSession,从而解决了问题。

这次调试不仅让我对Spring整合MyBatis有了更深入的理解,也让我对动态代理有了更深刻的认识。后续我将继续分享我的学习心得。

转载地址:http://tqye.baihongyu.com/

你可能感兴趣的文章
PostgreSQL 辟谣存在任意代码执行漏洞:消息不实
查看>>
PostgreSQL+PostGIS实现两坐标点之间最短路径查询算法函数(地图工具篇.12)
查看>>
Qt开发——简易调色板QPalette
查看>>
PostgreSQL-解决连接时遇到的乱码问题
查看>>
PostgreSQL15.2最新版本安装_远程连接_Navicat操作_pgAdmin操作_Windows10上安装---PostgreSQL工作笔记001
查看>>
PostgreSQL9.1 双机部署配置(主备数据同步)
查看>>
Qt开发——简易网络浏览器(一)
查看>>
Qt开发——简易成绩登记系统
查看>>
Postgresql中PL/pgSQL代码块的语法与使用-声明与赋值、IF语句、CASE语句、循环语句
查看>>
Postgresql中PL/pgSQL的游标、自定义函数、存储过程的使用
查看>>
SpringBoot中集成XXL-JOB分布式任务调度平台,轻量级、低侵入实现定时任务
查看>>
Postgresql中的表结构和数据同步/数据传输到Mysql
查看>>
Postgresql中自增主键序列的使用以及数据传输时提示:错误:关系“xxx_xx_xx_seq“不存在
查看>>
SpringBoot中集成websocket后WebSocketServer中注入mapper为空
查看>>
postgreSQL入门命令
查看>>
PostgreSQL删除数据库报"ERROR: There is 1 other session using the database."
查看>>
Qt开发——爱情公寓人事管理系统
查看>>
Qt开发——文件下载软件
查看>>
PostgreSQL和Oracle两种数据库有啥区别?如何选择?
查看>>
Qt开发——多线程网络时间服务器端
查看>>