一篇读懂--mybatis的缓存

一篇读懂–mybatis的缓存

MyBatis的缓存指的是缓存查询结果,当以后使用相同的sql语句、传入相同的参数进行查询时,可直接从mybatis本地缓存中获取查询结果,而不必查询数据库。

mybatis的缓存包括一级缓存、二级缓存,一级缓存默认是开启的,二级缓存默认是关闭的。

一级缓存:
在这里插入图片描述

SqlSession级别:在SqlSession中有一个Map,key是由sql语句、参数等信息组成的唯一值,value是查询出来的结果对象。
好处: 减小数据库压力
如何失效 :只要此sqlSession调用了、、这些会修改数据库的元素,就会清空此sqlSession的一级缓存,不管有没有使用commit()提交。
举例:

        User user1 = mapper.queryUserById(1);User user2 = mapper.queryUserById(1);

第一次查询时,就将查询结果放到一级缓存中。
如果后续使用的sql语句相同、传入的实参也相同,则结果对象也会相同,直接从一级缓存中获取结果对象,不再查询数据库。

        User user1 = mapper.queryUserById(1);sqlSession.commit();User user2 = mapper.queryUserById(1);

如果此sqlSession调用了commit()方法,会自动清空此sqlSession的一级缓存。
因为使用commit(),会将修改提交到数据库,下一次相同的查询,查询结果可能变了,之前的一级缓存不能再用,所以会自动清空。

下面用spring整合mybatis来测试一下mybatis的一级缓存:
1、下面是service层实现, 可以看到,我两次查询了同一个数据,理论上由于mybatis中默认开启一级缓存, 那么第二次肯定时要从缓存中获取,而不是创建SqlSession对象重新从数据库获取:

@Autowired
private LsjmUserMapper lsjmUserMapper;@Override
public LsjmUser getUser() {// 第一次查询LsjmUser user = lsjmUserMapper.getUserByName("300");System.out.println(user.toString());// 第二次查询LsjmUser user1 = lsjmUserMapper.getUserByName("300");System.out.println(user1.toString());return user;
}

从日志信息可以很明显的看到,代码中的两次查询构建了两个SqlSession对象,也就是说第二次查询并没有从前一次的SqlSession缓存中获取,而是自己新建一个SQLSession对象,重新查询;这样看来,一级缓存好像失效了?
在这里插入图片描述
这是为什么呢?因为我们没有加@Transaction注解
spring 中 结合 mybatis中,默认情况下,数据库处于自动提交模式,每一条sql语句处于一个单独的事务中,语句执行完毕时,如果执行成功则隐式提交事务。而mybatis的一级缓存在这种情况下是无效的,想要一级缓存起作用,则要开启事务:

开启事务: spring使用ThreadLocal获取当前资源绑定同一个SQLSession

未开启事务:每次查询,spring关闭旧的SslSession,创建一个新的Sqlsession对象,一级缓存补气作用

还有一种特殊情况,也会调用到缓存:

        ProcessDef list = processMapper.selectByPrimaryKey(5L);list.setCode("123");ProcessDef list1 = processMapper.selectByPrimaryKey(5L);

(注意,上面这个方法要加上@Transaction注解)
像上面这种情况,有时候在代码中也会出现,然后你就会找bug找半天都找不出问题;
结果是:list1的结果中的Code字段是“123”,而不是数据库中的那个字段!是不是不可思议,你可以自己在本地试试,事实就是如此。
原因是什么呢? 上面第一次查询直接去数据库查,这个可以理解, list.setCode(“123”);之后,第一次查询出来的缓存就已经变了,其中code字段就变成123了,所以这也是list1中code字段为123的原因!(这种情况大家要留意一下,搞了我半天的时间去找bug)
二级缓存:
mapper级别,同一个namespace下的mapper,有一个Map。
在这里插入图片描述

SqlSession sqlSession1 = MyBatisUtils.getSqlSession();UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class);User user1 = mapper1.queryUserById(1);System.out.println(user1);SqlSession sqlSession2 = MyBatisUtils.getSqlSession();UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class);User user2 = mapper2.queryUserById(1);System.out.println(user2);

不使用二级缓存,会执行2次查询。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/558819.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring Boot————BeanCreationNotAllowedException异常分析

引言 在对数据库进行新增记录的JUnit测试时,抛出一个BeanCreationNotAllowedException异常: 异常分析与解决 异常信息太长,图片截不下,粘贴来看: Exception in thread "pool-2-thread-1" org.springframew…

一篇博客读懂设计模式之---委派模式

一篇博客读懂设计模式之—委派模式 委派模式可能大家听起来不太熟悉,但是在代码开发的时候却很好用,下面从几个方面来介绍一下 what:是什么? 委派模式:顾名思义,委托其他对象或者实例来帮我们完成任务&am…

XML模板解析————Dom4j解析xml案例分析

引言 目前项目中包含大量的xml模板文件,现就xml模板的数据解析、提取、及部分常用方法做简单的应用和总结。 一、XML文件转为Document对象 通过SAXReader对象的read方法,读取Document对象。 SAXReader reader new SAXReader(); Document document …

教你如何一篇博客读懂设计模式之—--工厂模式

一篇博客读懂设计模式之—工厂模式 工厂模式在我们日常开发的时候经常用到,相信大家都有了一定的了解,工厂模式是一种创建对象的设计模式,它提供一种创建对象的最佳方式。 主要过程是: 定义一个创建对象的接口,让其子…

Jackson快速入门

引言 上一篇博客《XML模板解析————Dom4j解析xml案例分析》简单讲解了关于xml模板的解析,使用到了dom4j,这篇文章其实算是个姊妹篇,都是对于目前工作中的一些任务,如xml、json相互解析所涉及到的知识。 但是相对于xml而言&am…

一篇文章读懂MySQL的各种联合查询

一篇文章读懂MySQL的各种联合查询 联合查询是指将两个或两个以上的表的数据根据一定的条件合并在一起! 联合查询主要有以下几种方式: 全连接:将一张表的数据与另外一张表的数据彼此交叉联合查询出来 举例如下: 先建两张表: CR…

Class.forName()、Class.class、getClass() 区别

问:简单谈谈你对 Java 中 Class.forName()、Class.class、getClass() 三者的理解? Class.class 的形式会使 JVM 将使用类装载器将类装入内存(前提是类还没有装入内存),不做类的初始化工作,返回 Class 对象…

教你如何一篇博客读懂设计模式之—--原型模式

教你如何一篇博客读懂设计模式之----原型模式 what:是什么 原型模式: 用于创建重复的对象,既不用一个属性一个属性去set和get,又不影响性能,原型模式产生的对象和原有的对象不是同一个实例,他们的地址也…

Java反射————Method根据方法名称字符串调用方法

引言 之前浏览廖雪峰老师的个人博客网站,无意间发现了关于在Java8中获取参数的方法,随手一转《Java 8中获取参数名称》,没想到今天遇到一个功能,非常符合这种反射调用的使用场景。回看了这篇之前转载的文章,然后根据自…

一篇文章看懂@Scheduled定时器/@Async/CompletableFuture

一篇文章看懂Scheduled定时器/Async/CompletableFuture Scheduled注解解析: 1.cron:最重要的一个参数 cron表达式[秒] [分] [小时] [日] [月] [周] [年]([年]可省略) 简单了解一下,网上有现成的工具 示例&#xff…

一篇搞懂HTTP协议

本文转自 :flyhero 码上实战《一个HTTP打趴80%面试者》 HTTP协议简介 HTTP(超文本传输协议)是应用层上的一种客户端/服务端模型的通信协议,它由请求和响应构成,且是无状态的。(暂不介绍HTTP2) 协议&…

注册gmail邮件,遇到“此电话号码无法用于进行验证”该怎么办

注册gmail邮件,遇到“此电话号码无法用于进行验证”该怎么办? 跟浏览器语言的设置有关,将语言改为英文即可,亲测有效!

Jackson高级操作————节点树

引言 继《Jackson快速入门》基础篇之后的树模型相关操作。 节点树模型 ObjectMapper构建JsonNode节点树,类似于DOM解析器的XML。 Testpublic void testJsonTree() throws JsonProcessingException, IOException {String jsonString "{\"name\":\…

spring源码分析第一天------源码分析知识储备

spring源码分析第一天------源码分析知识储备 Spring源码分析怎么学? 1、环境准备; 2、思路 看:是什么? 能干啥 想:为什么? 实践:怎么做? 调试的时候,完全可以在…

Jackson高级操作————流式API与JsonGenerator、JsonParser

引言 继《Jackson快速入门》之后的高级相关操作。 Jackson提供了一种对于性能要求应用程序操作json更加高效的方式——流式API,这种方式开销小,性能高,因此,如果应用程序或者程序逻辑对于性能有一定要求,可以使用这种…

Mysql高级教程思维导图

Mysql高级教程思维导图 1、思维导图总览: 2、MySQL架构介绍: 2.1、MySQL简介 2.2、MySQL Linux版安装 2.3、MySQL配置文件 2.4、MySQL逻辑架构介绍 2.5、MySQL存储引擎 2.6、MySQL的用户和权限管理 2.7、MySQL一些杂项配置 ’ 3、索引优化分析 3.1、性…

Eclipse(STS 4)闪退导致EGit插件异常

引言 到目前为止,STS已经闪退过三次了。 问题很棘手,我需要冷静。 首先出现了一个问题就是,EGit无法commit。 第二个问题是切换分支报错。 闪退重启后EGit无法提交代码 观察闪退出现的时机,一般出现在我 commit 代码的时候&…

spring源码分析第二天------spring系统概述以及IOC实现原理

1、Spring5 概述 Spring 是一个开源的轻量级 Java SE(Java 标准版本)/Java EE(Java 企业版本)开发应用框架, 其目的是用于简化企业级应用程序开发。 Spring 框架除了帮我们管理对象及其依赖关系,还提供像通…

Linux进阶之路————Linux概述

引言 Linux是一个开源、免费的操作系统。学习Linux知识分为以下几个阶段: 第一阶段:Linux环境下的基本操作命令,包括文件操作命令(rm、mkdir、chmod、chown)编辑工具使用(vi、vim)Linux用户管…

spring源码分析第三天------spring核心IOC容器和依赖注入原理

基于XML的依赖注入 1、依赖注入发生的时间 当 Spring IOC 容器完成了 Bean 定义资源的定位、载入和解析注册以后,IOC 容器中已经管理类 Bean 定义的相关数据,但是此时 IOC 容器还没有对所管理的 Bean 进行依赖注入,依赖注入在以下两种情况 …