#Mybatis 关于mybatis的一级缓存

2023-11-09

# 本篇文章主要是为了帮助自己总结和加深理解,若能帮助到其他小伙伴也是极好的

基本介绍

        Mybatis中支持一级缓存和二级缓存,一级缓存是默认开启的并且不能关闭,二级缓存默认关闭,可根据需要进行手动开启,总体来说Mybatis的一二级缓存的最终目的就是为了帮助数据库减轻压力,保证高效高速的查询,提高数据库的瓶颈。


一级缓存

        一级缓存是基于hashmap的本地缓存,作用域只在session中,当session刷新或关闭后,这个session中所有的cache就会被清空。

        注意 如果使用clearCache以及增、删、改的sql进行操作会导致select缓存被清空。

命中原则

        mybatis是怎样判断两次select语句是完全相同的查询sql?

        1、statementId

        statementId其实就是select语句标签中的的id,如果两条select的id不同,那么必定不会命中。

例如图中代码,这是两条相同的select查询语句,先使用getByName01进行查询,再使用getByName02以及相同的参数进行查询,仍然不会进入缓存。

<select id="getByName01">
    SELECT * FROM `user` WHERE name=#{name}
<select/>

<select id="getByName02">
    SELECT * FROM `user` WHERE name=#{name}
<select/>

         2、查询参数

        若两次查询必须使用同一条statementId的sql,并且传入的参数一样,否则无法命中缓存。

        这里要注意的是,mybatis不论你在java代码中使用何种方式进行传参,只要最终sql语句中获取的参数相等就可以判定为是相同的参数。

        我们编写一条根据name查询的select,并且使用Map传参。

<select id="getByName" parameterType="java.util.Map" resultType="user">
    SELECT * FROM `user` WHERE name=#{name}
<select/>

         在两次查询中,我们传入两个不同的hashmap参数(只有name会传入sql中),结果会怎样?第二次查询使用缓存还是查询数据库?

public void test(){
    // 第一次查询
    HashMap param1 = new HashMap();
    param1.put("name","alix");
    param1.put("test",123);
    mapper.getUserByName(param1);

    // 第二次查询
    HashMap param2 = new HashMap();
    param2.put("name","alix");
    param1.put("test",321);
    mapper.getUserByName(param2);
}

        通过测试执行,第二次查询竟然没有去数据库查询,而是读取了第一次查询的缓存,通过查看sql日志我们发现sql编译的结果如图所示。

        ==>>   Preparing:SELECT * FROM user WHERE name=?

        ==>>Parameters:alix(Integer)

        <<==            Total:1

         所以,参数相同指的是最终传递到sql中的参数只要是一样的就可以满足条件。

        3、分页参数

        这里的分页指的是mybatis自带的分页功能,很多人可能不熟悉或者很少使用,因为它是查询出数据库的所有数据到本地进行一个物理分页,而不是直接从数据库获取分页之后的结果,这样的一个操作执行效率很低,非常损耗性能,所以也不推荐使用(这里不做过多说明)。

        4、sql语句

        顾名思义,mybatis要求我们查询时使用的sql语句必须相同。但值得注意的是,这里所说的sql语句必须相同指的是这条语句加上参数最终拼接形成完整的sql文本必须完全一样。

        也就是说在查询时并不会考虑sql语句本身的语义,如下代码所示。

<select id="getUserByNameInGender">
    <if test="gender == 0">
        SELECT * FROM user WHERE name=#{name}
    </if>
    <if test="gender == 1">
        SELECT * FROM user WHERE 1=1 AND name=#{name}
    </if>
</select>

        我们知道

                SELECT * FROM user WHERE 1=1 AND name=#{name}SELECT * FROM user WHERE name=#{name}

                其实是两个意义完全相同的sql语句,但mybatis并不会考虑这种情况。

总结

        mybatis的一级缓存在什么时候产生?在什么情况下销毁?

        产生:

                在使用select标签进行查询时才会产生缓存,如果我们在诸如update标签中使用select语句进行查询并不会产生缓存。

        销毁:

                一级缓存是维持在同一个sqlsession中的,因此在对sqlsession使用close关闭或commit提交后,缓存就会被清空;

                在使用sqlsession.rollback()进行回滚时,也会导致缓存被清空;

                进行update操作也会造成缓存被清空,并且dll语句对查询缓存的影响并不局限于同一张表,就是说在A表进行查询产生缓存,然后对B表进行dll操作同样会使A表的select缓存失效(并且是所有缓存);

                sqlsession还提供了clearCache()方法,这个方法可以让我们主动的对缓存进行清空;

        经常有提到说mybatis一级缓存可能导致脏读的情况,是否真实?为什么?怎么解决?

        针对mybatis一级缓存可能存在产生脏读的情况,我们可以模拟并发情况下的执行步骤来进行分析;

        

        如果按照图中步骤来看,mybatis一级缓存的确存在可能造成脏读的情况;

        所以在实际开发环境中应该避免使用mybatis缓存,而是使用类似redis这样的第三方插件进行全局缓存的管理;

补充

        一级缓存的hashmap中key和value分别存的是?

        key:hashcode值 + sqlId + sql语句;

        value:映射结果对象;


后言

你好,很高兴认识你

        本次关于 “ mybatis一级缓存 ” 的文章到此完结,若有疑问可以私信与我交流。

        如果你也喜欢编程,如果你也喜欢敲代码,如果你也喜欢技术,欢迎联系~

        我是

                爱敲代码的小王bro

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

#Mybatis 关于mybatis的一级缓存 的相关文章

随机推荐

  • windows下激活conda环境

    windows activate env name linux source root autodl tmp environment bgmv30222 bin activate
  • (2003, "Can't connect to MySQL server on 'IP' ([WinError 10061] 由于目标计算机积极拒绝,无法连接。)")

    2003 Can t connect to MySQL server on IP WinError 10061 与MySql 只能访问localhost 和 127 0 0 1访问 不能通过其他IP访问 问题描述 项目中跨域请求数据 在远程
  • 华为od机试 Python【游戏最高分】

    题目 小明正在和他的朋友们玩一个跳格子的游戏 这个游戏有一个行列 共包含n个格子 每个格子里都有一定的分数 游戏的规则如下 小明可以选择任意一个格子作为起点 从起点开始 小明可以选择跳到任意非相邻的格子 也就是说 如果小明当前在第i个格子
  • java中的resultset类详解

    一 JDBC sun 提供了一套通用性的接口 可以连接任何的数据库 连接数据库的具体得到实例 具体的数据库厂商实现的 连接数据的步骤 别忘了复制jar包 1 注册驱动 Class forName DriverManager 2 获得链接对象
  • CMD中提升帐户到管理员权限

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 提升用户权限 从打开的 命令提示符 窗口中 输入命令 net localgroup administrators 用户名 add 并按回车 即可给当前 用户名 提升为 管理
  • C++函数返回引用

    首先需要明白 C 函数为什么要返回引用 答 这样就不用返回结果的副本 因为返回副本需要做赋值拷贝函数 浪费时间 这时候 实际上 返回是结果的副本 而不是结果本身 如果要返回本身 就返回引用就OK了 例1 const string manip
  • 数据分析入门宝藏!《Python数据分析-从入门到实践》

    在大数据 人工智能时代 数据无处不在 无论处于哪种行业 能够掌握一定的数据分析技能必然是职场的加分项 本笔记提供了丰富的学习内容 包含230个快速示例 17个案例 4个项目 力求为读者打造一本 学习入门 应用 实践一体化 的的Python数
  • Presto 常用配置及操作

    一 介绍 Presto是一个开源的分布式SQL查询引擎 适用于交互式分析查询 数据量支持GB到PB字节 Presto的设计和编写完全是为了解决像Facebook这样规模的商业数据仓库的交互式分析和处理速度的问题 推荐阅读 Presto实现原
  • DVWA 通关XSS(Stored)

    存储型XSS 持久化跨站脚本 持久性体现在XSS代码不是在某个参数 变量 中 而是写进数据库文件等可以永久保存数据的介质中 存储型XSS通常发生在留言板等地方 可以在留言板位置进行留言 将恶意代码写进数据库中 Low 没有任何过滤 直接使用
  • 开源云同步的markdown写作软件——Yosoro

    文章目录 前言 简便的项目管理 舒服的写作体验 支持one driver 存在缺点 前言 Yosoro是一款支持在Win Linux macOS上使用的写作软件 它的界面设计以及交互上表达出的极简主义可以让用户们可以完全沉浸于自己写作世界
  • MyBatis学习——第四篇(拦截器和拦截器分页实现)

    MyBatis架构体图 1 mybatis核心对象 从MyBatis代码实现的角度来看 MyBatis的主要的核心部件有以下几个 SqlSession 作为MyBatis工作的主要顶层API 表示和数据库交互的会话 完成必要数据库增删改查功
  • 【git体验】git基础-3目录之间关系

    1 git目录和工作目录 Git目录并不是Bare repo 而是本地的代码库 即用git init命令在根目录创建的 git 目录 类似SVN的 svn 目录 这个目录就是git实现分布式代码管理的关鍵了 工作目录就是 git的上級目录
  • Angular&TypeScript 经验技巧

    TypeScript 变量声明 var 变量名 类型 值 基本类型 数据类型 关键字 描述 任意类型 any 声明为 any 的变量可以赋予任意类型的值 数字类型 number 双精度 64 位浮点值 它可以用来表示整数和分数 let bi
  • 使用HAL库开发STM32:使用Timer输出PWM信号

    文章目录 目的 基础说明 输出PWM信号 总结 目的 单片机输出PWM信号是很常用的一种功能需求 STM32中通常使用Timer来输出PWM信号 这篇文章将对相关内容做个说明 基础说明 在使用Timer输出PWM信号需要了解一些Timer的
  • Spring Boot, 访问入口配置

    HTTP Server port server port 8080 Make the application accessible on the given context path http localhost 8080 myapp se
  • openGL结合光照与纹理

    openGL系列文章目录 文章目录 openGL系列文章目录 前言 一 实现思路 二 代码 1 c 主程序 2 顶点着色器 3 片元着色器 运行效果 参考 源码下载 前言 在光照模型中 都是假设我们使用按ADS 定义的光源 照亮按ADS 定
  • Python计算商品复购率

    1 Python计算产品复购率 需求 给出数据商品购买数据 数据格式 csv 包含 购买月份 手机号 根据该数据计算产品的复购率 复购率算法 算法一 单位时间内 按每月 R 复购人数 总购买人数 算法二 单位时间内 按每月 R 复购交易次数
  • 应用usb_cam同时打开多个摄像头方法

    最近由于项目需要 需要同时开启多个摄像头 虽然可以用opencv去写对应的摄像头开启的程序 但是 还是想用ros中提供的usb cam去打开多个摄像头 通过usb cam去打开一个摄像头 不用下载源码 可以直接安装usb cam去调用lau
  • 使用GDI/GDI+绘制到D3D9缓冲区的方法

    这个其实是3D绘图里嵌入2D绘图的传统方式 D3D9直接使用GDI GDI 就可以画图 只不过需要额外的设置 而且只支持RGB和XRGB 不支持ARGB 因此这种方法比较适合合成UI元素和不透明的纹理贴图 不适合将要进行AlphaBlend
  • #Mybatis 关于mybatis的一级缓存

    本篇文章主要是为了帮助自己总结和加深理解 若能帮助到其他小伙伴也是极好的 基本介绍 Mybatis中支持一级缓存和二级缓存 一级缓存是默认开启的并且不能关闭 二级缓存默认关闭 可根据需要进行手动开启 总体来说Mybatis的一二级缓存的最终