mybatis的缓存机制

视频教程_免费高速下载|百度网盘-分享无限制 (baidu.com)

MyBatis 有一套灵活而强大的缓存机制,主要分为两级缓存:一级缓存(本地缓存)和二级缓存(全局缓存)。

  1. 一级缓存(本地缓存)

    • 一级缓存是 MyBatis 默认开启的缓存,它指的是在同一个 SqlSession 中执行相同 SQL 语句时,第一次查询的结果会被缓存起来,后续再执行相同的查询,直接从缓存中获取结果,而不再去查询数据库。

    • 一级缓存是基于 SqlSession 的生命周期的,当 SqlSession 关闭时,一级缓存也就失效了。

    • 一级缓存可以通过清空缓存或提交事务来手动刷新,默认情况下,只要 SqlSession执行一条语句,就会刷新,不会等到 SqlSession结束(不像二级缓存)

    • 一级缓存,在进行DML操作后,会使得缓存失效

    • 一个会话DML操作只会重置当前会话的缓存,不会重置其他会话的缓存,也就是说,其他会话缓存是不会更新的!

  2. 二级缓存(全局缓存)

    • 二级缓存是全局缓存,可以跨多个 SqlSession 共享缓存,但是只有当一个SqlSession结束之后会刷新二级缓存。所以当 SqlSession1和 SqlSession2都没结束且查询同样内容的时候,不会调用二级缓存,因为二级缓存啥都没有。

    • 二级缓存需要在 MyBatis 的配置文件中进行配置启用,并且需要在映射文件中指定哪些语句使用二级缓存。

      不希望某个方法开启缓存呢?我们可以添加useCache属性来关闭缓存:

      <select id="getStudentBySid" resultType="Student" useCache="false">select * from student where sid = #{sid}
      </select>
    • 对于同一个 namespace 下的语句,如果开启了二级缓存,它们的查询结果会被缓存在一个全局的缓存区域中,当其他 SqlSession 执行相同的查询时,可以从全局缓存中获取结果。

    • 二级缓存是基于 namespace 级别的,不同的 namespace 有独立的缓存区域,它们之间不会相互影响。

    • 二级缓存默认是开启的,但需要在映射文件中明确指定 <cache/> 元素,才会对该 namespace 启用缓存。

      <mapper namespace="com.example.BlogMapper"><cacheeviction="FIFO"flushInterval="60000"size="512"readOnly="true"/><!-- 其他映射语句 -->
      </mapper>
      

      namespace="com.example.BlogMapper":指定缓存的 namespace,即当前映射文件所属的命名空间。这个命名空间用于标识二级缓存的作用范围,是一个唯一的标识符,通常与映射器接口或者类的全路径名相对应。eviction="FIFO":指定缓存的淘汰策略。在这里,FIFO 表示采用先进先出(First In, First Out)策略,即最先进入缓存的数据最先被淘汰。flushInterval="60000":指定缓存刷新的时间间隔,单位为毫秒。在这里,设置为 60000 毫秒,即 60 秒,表示 MyBatis 会定期刷新缓存,清理过期的缓存项。size="512":指定缓存的最大项数。当缓存中的项数达到设定的值时,MyBatis 会尝试清理缓存。readOnly="true":指定是否只读。设置为 true 时,表示缓存只读,不会修改缓存中的数据,可以提高性能。默认值为 falsereadOnly="true":指定是否只读。设置为 true 时,表示缓存只读,不会修改缓存中的数据,可以提高性能。默认值为 false

    • 二级缓存的实现是可插拔的,可以自定义缓存实现,如使用 Ehcache、Redis 等。

    • 添加了二级缓存之后,会先从二级缓存中查找数据,当二级缓存中没有时,才会从一级缓存中获取,当一级缓存中都还没有数据时,才会请求数据库

需要注意的是,缓存机制虽然能提高查询性能,但在一些更新操作(例如插入、更新、删除)时,可能会导致缓存的数据不一致。因此,在执行这类操作时,MyBatis 会自动清空相关的缓存,保证数据的正确性。开发者也可以通过手动清理缓存来控制缓存的行为。

虽然缓存机制给我们提供了很大的性能提升,但是缓存存在一个问题,我们之前在计算机组成原理中可能学习过缓存一致性问题,也就是说当多个CPU在操作自己的缓存时,可能会出现各自的缓存内容不同步的问题,而Mybatis也会这样,我们来看看这个例子:

public static void main(String[] args) throws InterruptedException {try (SqlSession sqlSession = MybatisUtil.getSession(true)){TestMapper testMapper = sqlSession.getMapper(TestMapper.class);while (true){Thread.sleep(3000);System.out.println(testMapper.getStudentBySid(1));}}
}

我们现在循环地每三秒读取一次,而在这个过程中,我们使用IDEA手动修改数据库中的数据,将1号同学的学号改成100.

结果是依小明的sid并没有发生改变,这也证明了Mybatis的缓存在生效,因为我们是从外部进行修改,Mybatis不知道我们修改了数据,所以依然在使用缓存中的数据,但是这样很明显是不正确的,因此,如果存在多台服务器或者是多个程序都在使用Mybatis操作同一个数据库,并且都开启了缓存,需要解决这个问题,要么就得关闭Mybatis的缓存来保证一致性

<settings><setting name="cacheEnabled" value="false"/>
</settings>

cacheEnabled 是一个全局开关,用于控制是否开启缓存。在这里,将其值设置为 false,表示禁用缓存。 

<select id="getStudentBySid" resultType="Student" useCache="false" flushCache="true">select * from student where sid = #{sid}
</select>
  • useCache="false":这个属性用于指定是否使用缓存。在这里,useCache 被设置为 false,表示禁用缓存。即使全局缓存配置是启用的,这个查询也不会使用缓存。

  • flushCache="true":这个属性用于指定是否刷新缓存。在这里,flushCache 被设置为 true,表示在执行这个查询之前会刷新(清空)缓存。即使全局缓存是启用的,这个查询会强制刷新缓存,确保获取最新的结果。

要么就需要实现缓存共用,也就是让所有的Mybatis都使用同一个缓存进行数据存取,在后面,我们会继续学习Redis、Ehcache、Memcache等缓存框架,通过使用这些工具,就能够很好地解决缓存一致性问题

 

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

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

相关文章

Android学习之路(22) 从模块化到组件化

从模块化到组件化 一、从模块化到组件化 Android 应用项目 , 都存在一个应用模块 ( Application Module ) , 在 build.gradle 构建脚本中 , 第一个插件配置 com.android.application , 表明 该 Module 编译打包后的输出是 APK 安装包 ; 该项目可以直接运行 ; plugins {id co…

用pandas实现用前一行的excel的值填充后一行

今天接到一份数据需要分析&#xff0c;数据在一个excel文件里&#xff0c;内容大概形式如下&#xff1a; 后面空的格子里的值就是默认是前面的非空的值&#xff0c;由于数据分析的需要需要对重复的数据进行去重&#xff0c;去重就需要把控的cell的值补上&#xff0c;然后根据几…

c/c++的指针函数与函数指针

函数 定义&#xff1a; 函数是数学中的一个概念&#xff0c;它是定义在某个数集上的一个特殊的映射关系。函数将输入值&#xff08;或自变量&#xff09;映射到输出值&#xff08;或因变量&#xff09;。函数的输入和输出可以是任何类型的数据&#xff0c;如数字、字符串、数组…

中霖教育:注册会计师与中级会计师有什么区别?

在财会行业&#xff0c;注册会计师与中级会计师是两种不同的职业证书&#xff0c;二者之间有很大的区别&#xff0c;都有很高的含金量&#xff0c;考生们可以根据自身情况进行选择&#xff0c; 1.证书性质不同 注册会计师属于基本资格&#xff0c;如果没有注会证书是不能从事…

uniapp使用自定义组件

tt.vue中使用video-player组件 用到的目录如下&#xff1a; pages.json {"path": "pages/Tabbar/tt/tt","style": {"navigationBarTitleText": "","enablePullDownRefresh": false,// 使用自定义组件"using…

B-Tree详解及编码实现

一、概念和特性 1、定义 B-Tree是一种平衡的多叉树&#xff0c;适用于外查找多路搜索树&#xff0c;这种数据结构能够保证数据节点查找、顺序访问、插入、删除的动作&#xff0c;其平均时间复杂读控制在O(logN)内;B树为系统大块数据的读写操作做了优化&#xff0c;少定位记录时…

U-Mamba: Enhancing Long-range Dependency for Biomedical Image Segmentation

Abstract 卷积神经网络(Convolutional Neural Networks, cnn)和transformer是生物医学图像分割中最流行的架构&#xff0c;但由于固有的局部性或计算复杂性&#xff0c;它们处理远程依赖关系的能力有限。为了解决这一挑战&#xff0c;我们引入了U-Mamba&#xff0c;一个通用的…

WPF-HelixToolkit包的使用(上)

1、引入HelixToolkit包&#xff1a;新建一个WPF项目&#xff0c;在项目“引用”上右击&#xff0c;选择“管理NutGet程序包”&#xff0c; 2、在左侧“浏览”中输入“helixtoolkit” 3、安装第一个“HelixToolkit”包 4、解决错误&#xff1a;右击属性->应用程序->目标框…

Web03--CSS进阶

1、CSS常用属性 1.1 文本字体相关属性设置 样式名 描述 text-align 设置内容位置 text-decoration 控制下划线 none没有 underline有 line-hight 行高 font-size 设置字体大小 font-weight 设置字体粗细的 font-famliy 设置字体样式 letter-spacing 设置中文字…

MySQL索引的使用,大大提升你代码的效率

目录 &#x1f680;索引使用 &#x1f680;最左前缀法则 &#x1f680;范围查询 &#x1f680;索引失效情况 隐式类型转换是什么&#xff1f; 隐式类型转换的影响 举例说明 无隐式类型转换的情况 存在隐式类型转换的情况 总结 &#x1f680;模糊查询 &#x1f680;or…

【华为 ICT HCIA eNSP 习题汇总】——题目集7

1、一台 PC 的 MAC 地址是 5489-98FB-65D8 &#xff0c;管理员希望该 PC 从 DHCP 服务器获得指定的 IP 地址为192.168.1.11/24&#xff0c;以下命令配置正确的是&#xff08;&#xff09;。 A、dhcp static-bind ip-address 192.168.1.11 24 mac- address 5489-98FB-65D8 B、dh…

这个零售行业销售工具,老板都惊呆了!

在数字化时代&#xff0c;零售业正在经历一场深刻的变革&#xff0c;新零售模式逐渐成为业界的焦点。在这个变革的浪潮中&#xff0c;自动售货机以其智能、便捷的特性崭露头角&#xff0c;成为零售业的一项创新力量。 客户案例 零食自动售货机 福州某食品公司部署了泛地缘科技…