1. Mybatis 的一级缓存

一级缓存是 SqlSession 级别的,通过同一个 SqlSession 查询的数据会被缓存,下次查询相同的数据,就会从缓存中直接获取,不会从数据库重新访问 , 一级缓存时默认开启的

使一级缓存失效的四种情况:

  • 1) 不同的 SqlSession 对应不同的一级缓存

  • 2) 同一个 SqlSession 但是查询条件不同

  • 3) 同一个 SqlSession 两次查询期间执行了任何一次增删改操作

  • 4) 同一个 SqlSession 两次查询期间手动清空了缓存

对于 Mybatis 一级缓存的理解:

Mybatis 的一级缓存是指默认开启的、基于 SqlSession 的缓存。当应用程序执行查询操作时,首先查询一级缓存,如果命中缓存,则直接返回命中的结果,否则查询数据库,并将查询结果缓存到一级缓存中。在同一个 SqlSession 内,如果对同一个查询再次执行,则会直接从缓存中获取结果,而不需要再次查询数据库。一级缓存对于减少对数据库的访问,提高应用程序的性能有着重要的意义。

Mybatis 中一级缓存的默认实现是基于一个 HashMap 的内存缓存,其中缓存的 key 由 SQL 语句、查询参数、环境 ID 组成,value 为查询结果列表。缓存的数据是和 SqlSession 相关的,并且在 SqlSession 的生命周期中有效。一级缓存是 SqlSession 级别的缓存,意味着同一个 SqlSession 中的所有操作共享缓存,但不同的 SqlSession 中缓存是相互独立的。

一级缓存的优点是可以有效地减少对数据库的访问,提高查询效率,是 Mybatis 的默认缓存策略。同时,由于缓存数据是绑定到 SqlSession 对象的,因此不需要进行额外的配置,使用上非常方便。但是,一级缓存存在以下问题:

  1. 数据库数据更新问题:当进行数据库数据的更新操作时,容易出现数据同步问题。由于一级缓存是和 SqlSession 绑定的,同一个 SqlSession 中的缓存数据并不会自动失效或更新,因此当其他 SqlSession 更新了相同的数据时,当前 SqlSession 中的缓存数据就会过期,而使用缓存数据就会导致数据不一致。因此,为了解决这个问题,需要手动清除或刷新缓存,或者选择使用二级缓存。
  2. 内存占用问题:一级缓存中所有的缓存数据都是存放在内存中的,如果缓存的数据过多,则容易消耗过多的内存资源,导致系统运行缓慢或者内存溢出。

因此,在使用 Mybatis 进行数据访问时,需要根据实际业务场景和性能要求,合理地使用一级缓存和二级缓存,以达到更好的性能和缓存效果。

2. Mybatis 的二级缓存

二级缓存是 SqlSessionFactory 级别,通过同一个 SqlSessionFactory 创建的 SqlSession 查询的结果会被

缓存;此后若再次执行相同的查询语句,结果就会从缓存中获取

二级缓存开启的条件:

  • a>在核心配置文件中,设置全局配置属性 cacheEnabled="true",默认为 true,不需要设置

  • b>在映射文件中设置标签

  • c>二级缓存必须在 SqlSession 关闭或提交之后有效

  • d>查询的数据所转换的实体类类型必须实现序列化的接口

使二级缓存失效的情况:

两次查询之间执行了任意的增删改,会使一级和二级缓存同时失效

2.1 对于 Mybatis 二级缓存的理解

Mybatis 的二级缓存是一种全局的缓存,对于同一个 Mapper 中的多个 SqlSession 是共享的。它将数据缓存在应用程序进程的内存中,相比于一级缓存的局部缓存,二级缓存是全局性的进程内缓存,可以被多个 SqlSession 共享,并且可以跨越多个 SqlSession 的生命周期。

通过开启 Mybatis 的二级缓存,可以避免因为一级缓存的使用不当而导致的数据不一致问题,提高应用程序的性能。

Mybatis 的二级缓存是由一个叫做 Cache 的接口来定义的,可以通过配置相关的 Cache 实现来进行二级缓存的管理。Mybatis 内置了几个常用的 Cache 实现,包括基于内存的 LRU 算法的 PerpetualCache 和基于 EhCache 的实现,用户也可以自定义 Cache 实现来满足特定的需求。

开启二级缓存的方式如下:

  1. 将全局配置文件中的 <setting name="cacheEnabled" value="true"/>​ 设置为 true,开启二级缓存
  2. 如果需要对某个 Mapper 开启二级缓存,需要在对应的 Mapper 配置文件中添加 <cache/>​ 标签,并设置相关属性

Mybatis 的二级缓存的使用需要注意以下几点:

  1. 执行插入、更新、删除等操作时需要清空缓存,避免脏数据出现。
  2. 需要在需要使用缓存的 Mapper 配置文件中手动配置 <cache/>​ 标签进行配置,以及相关缓存策略。
  3. 二级缓存中的数据会被多个 SqlSession 共享,因此只有被序列化的实体才能放到缓存中,而且如果实体类发生变化,所有的缓存将失效。
  4. 对于不同表格的数据应该使用不同的命名空间进行缓存隔离。

二级缓存的优点是可以提高应用程序的性能,适用于需要共享数据的应用程序场景。但也同时带来了一些管理和维护成本,需要注意缓存的清理和更新。

3. 二级缓存的相关配置

在 mapper 配置文件中添加的 cache 标签可以设置一些属性:

①eviction 属性:缓存回收策略,默认的是 LRU。

  • LRU(Least Recently Used) – 最近最少使用的:移除最长时间不被使用的对象。

  • FIFO(First in First out) – 先进先出:按对象进入缓存的顺序来移除它们。

  • SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。

  • WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。

②flushInterval 属性:刷新间隔,单位毫秒

  • 默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新

③size 属性:引用数目,正整数

  • 代表缓存最多可以存储多少个对象,太大容易导致内存溢出

④readOnly 属性:只读, true/false

  • true:只读缓存;会给所有调用者返回缓存对象的相同实例。因此这些对象不能被修改。这提供了 很重要的性能优势。

  • false:读写缓存;会返回缓存对象的拷贝(通过序列化)。这会慢一些,但是安全,因此默认是 false。

4. MyBatis 缓存查询的顺序

先查询二级缓存,因为二级缓存中可能会有其他程序已经查出来的数据,可以拿来直接使用。

如果二级缓存没有命中,再查询一级缓存

如果一级缓存也没有命中,则查询数据库

SqlSession 关闭之后,一级缓存中的数据会写入二级缓存

5. 整合第三方缓存 EHCache (了解)

5.1 添加依赖

<!-- Mybatis EHCache整合包 -->
<dependency>
   <groupId>org.mybatis.caches</groupId>
   <artifactId>mybatis-ehcache</artifactId>
   <version>1.2.1</version>
</dependency>
<!-- slf4j日志门面的一个具体实现 -->
<dependency>
   <groupId>ch.qos.logback</groupId>
   <artifactId>logback-classic</artifactId>
   <version>1.2.3</version>
</dependency>

5.2 各 jar 包功能

jar 包名称 作用
mybatis-ehcache Mybatis 和 EHCache 的整合包
ehcache EHCache 核心包
slf4j-api SLF4J 日志门面包
logback-classic 支持 SLF4J 门面接口的一个具体实现

5.3 创建 EHCache 的配置文件 ehcache.xml

<?xml version="1.0" encoding="utf-8" ?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
<!-- 磁盘保存路径 -->
<diskStore path="D:\atguigu\ehcache"/>
<defaultCache
       maxElementsInMemory="1000"
       maxElementsOnDisk="10000000"
       eternal="false"
       overflowToDisk="true"
       timeToIdleSeconds="120"
       timeToLiveSeconds="120"
       diskExpiryThreadIntervalSeconds="120"
       memoryStoreEvictionPolicy="LRU">
</defaultCache>
</ehcache>

5.4 设置二级缓存的类型

<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>

5.5 加入 logback 日志

存在 SLF4J 时,作为简易日志的 log4j 将失效,此时我们需要借助 SLF4J 的具体实现 logback 来打印日志。 创建 logback 的配置文件 logback.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="true">
<!-- 指定日志输出的位置 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
           <!-- 日志输出的格式 -->
           <!-- 按照顺序分别是: 时间、日志级别、线程名称、打印日志的类、日志主体内容、换行-->
<pattern>[%d{HH:mm:ss.SSS}] [%-5level] [%thread] [%logger][%msg]%n</pattern>
</encoder>
</appender>
   <!-- 设置全局日志级别。日志级别按顺序分别是: DEBUG、INFO、WARN、ERROR -->
   <!-- 指定任何一个日志级别都只打印当前级别和后面级别的日志。 -->
   <root level="DEBUG">
<!-- 指定打印日志的appender,这里通过“STDOUT”引用了前面配置的appender -->
<appender-ref ref="STDOUT" />
</root>
<!-- 根据特殊需求指定局部日志级别 -->
<logger name="com.atguigu.crowd.mapper" level="DEBUG"/>
</configuration>

5.6 EHCache 配置文件说明

属性名 是否必须 作用
maxElementsInMemory 在内存中缓存的 element 的最大数目
maxElementsOnDisk 在磁盘上缓存的 element 的最大数目,若是 0 表示无穷大
eternal 设定缓存的 elements 是否永远不过期。 如果为 true,则缓存的数据始终有效, 如果为 false 那么还要根据 timeToIdleSeconds、timeToLiveSeconds 判断
overflowToDisk 设定当内存缓存溢出的时候是否将过期的 element 缓存到磁盘上
timeToIdleSeconds 当缓存在 EhCache 中的数据前后两次访问的时间超过 timeToIdleSeconds 的属性取值时, 这些数据便会删除,默认值是 0,也就是可闲置时间无穷大
timeToLiveSeconds 缓存 element 的有效生命期,默认是 0.,也就是 element 存活时间无穷大
diskSpoolBufferSizeMB DiskStore(磁盘缓存)的缓存区大小。默认是 30MB。每个 Cache 都应该有自己的一个缓冲区
diskPersistent 在 VM 重启的时候是否启用磁盘保存 EhCache 中的数据,默认是 false。
diskExpiryThreadIntervalSeconds 磁盘缓存的清理线程运行间隔,默认是 120 秒。每个 120s, 相应的线程会进行一次 EhCache 中数据的清理工作
memoryStoreEvictionPolicy 当内存缓存达到最大,有新的 element 加入的时候, 移除缓存中 element 的策略。 默认是 LRU (最近最少使用),可选的有 LFU (最不常使用)和 FIFO (先进先出)

10. Mybatis的缓存的更多相关文章

  1. MyBatis一级缓存引起的无穷递归

    MyBatis一级缓存引起的无穷递归 引言: 最近在项目中参与了一个领取优惠劵的活动,当多个用户领取同一张优惠劵的时候,使用了数据库锁控制并发,起初的设想是:如果多个人同时领一张劵,第一个到达的人领取 ...

  2. 【MyBatis源码解析】MyBatis一二级缓存

    MyBatis缓存 我们知道,频繁的数据库操作是非常耗费性能的(主要是因为对于DB而言,数据是持久化在磁盘中的,因此查询操作需要通过IO,IO操作速度相比内存操作速度慢了好几个量级),尤其是对于一些相 ...

  3. mybatis学习--缓存(一级和二级缓存)

    声明:学习摘要! MyBatis缓存 我们知道,频繁的数据库操作是非常耗费性能的(主要是因为对于DB而言,数据是持久化在磁盘中的,因此查询操作需要通过IO,IO操作速度相比内存操作速度慢了好几个量级) ...

  4. 三)mybatis 二级缓存,整合ehcache

    mybatis-config.xml <setting name="cacheEnabled" value="true" /> PersonMapp ...

  5. 0065 MyBatis一级缓存与二级缓存

    数据库中数据虽多,但访问频率却不同,有的数据1s内就会有多次访问,而有些数据几天都没人查询,这时候就可以将访问频率高的数据放到缓存中,就不用去数据库里取了,提高了效率还节约了数据库资源 MyBatis ...

  6. 如何细粒度地控制你的MyBatis二级缓存(mybatis-enhanced-cache插件实现)

    前几天网友chanfish 给我抛出了一个问题,笼统地讲就是如何能细粒度地控制MyBatis的二级缓存问题,酝酿了几天,觉得可以写个插件来实现这个这一功能.本文就是从问题入手,一步步分析现存的MyBa ...

  7. mybatis+springmvc缓存设置

    开始接触mybatis,本以为缓存设置好麻烦,在网上找了好多相关的资料,说得也都好复杂,经过自己亲自实践,其实很简单的. 首先引入需要的jar包,参照pom.xml配置: <!-- 缓存设置 s ...

  8. MyBatis 示例-缓存

    MyBatis 提供两种类型的缓存,一种是一级缓存,另一种是二级缓存,本章通过例子的形式描述 MyBatis 缓存的使用. 测试类:com.yjw.demo.CacheTest 一级缓存 MyBati ...

  9. Springboot整合Ehcache 解决Mybatis二级缓存数据脏读 -详细

    前面有写了一篇关于这个,但是这几天又改进了一点,就单独一篇在详细说明一下 配置 application.properties ,启用Ehcache # Ehcache缓存 spring.cache.t ...

  10. mybatis的缓存机制及用例介绍

    在实际的项目开发中,通常对数据库的查询性能要求很高,而mybatis提供了查询缓存来缓存数据,从而达到提高查询性能的要求. mybatis的查询缓存分为一级缓存和二级缓存,一级缓存是SqlSessio ...

随机推荐

  1. 关于Java基础中的异常处理知识点

    Java中的异常(Exception),史上最全的教程来啦~_smilehappiness的博客-CSDN博客 以及Java:详解Java中的异常(Error与Exception)_王小二(海阔天空) ...

  2. 系统评价——数据包络分析DEA的R语言实现(七)

    数据包络分析(Data envelopment analysis,DEA)是运筹学中用于测量决策部门生产效率的一种方法,它是基于相对效率发展的崭新的效率评估方法. 详细来说,通过使用数学规划模型,计算 ...

  3. vue之数组与对象的检测与更新

    目录 说明 语法 示例 说明 MVVM会自动检测变量的变化,当变量改变,页面也会对应的变化,但是有一点需要注意,如果有一个对象增加值的时候,不能直接修改,需要使用Vue.set()方法 语法 Vue. ...

  4. CentOS8 搭建Kubernetes

    CentOS8 搭建Kubernetes 主机名 IP 组件 k8s-master 192.168.40.128/24 kubeadm.kubelet.kubectl.docker-ce k8s-no ...

  5. 【Spring5】数据库事务操作

    Spring针对事务的操作 事务的概念:事务是数据库最基本的单元,逻辑上的一组操作,要么都成功,如果有一个操作失败则都失败. 事务的特性:ACID 原子性.一致性.隔离性.持久性 JavaEE环境三层 ...

  6. 借助 APISIX Ingress,实现与注册中心的无缝集成

    作者张晋涛,API7.ai 云原生技术专家,Apache APISIX PMC 成员,Apache APISIX Ingress Controller 项目维护者. 原文链接 云原生场景下是否需要服务 ...

  7. hasOwnProperty的作用、配合for in使用 、key in Object判读key

    我们都知道,对象以 key|value的形式存在 它和数组一样可以遍历,对象可以通过for in 去遍历,拿到遍历对象的所有key 某些idea在使用for in 时,提示代码片段中就有出现以下这种情 ...

  8. 深度学习-06(PaddlePaddle体系结构与基本概念[Tensor、Layer、Program、Variable、Executor、Place]线性回归、波士顿房价预测)

    文章目录 深度学习-06(PaddlePaddle基础) paddlePaddle概述 PaddlePaddle简介 什么是PaddlePaddle 为什么学习PaddlePaddle PaddleP ...

  9. Vue3 +element-plus+ wangEditor 富文本编辑器+前端七牛云上传

    我用的vue3,element-plus ,没用ts 搭建wangEditor 参考 地址 https://www.cnblogs.com/xbxxf/p/16791084.html 七牛云安装参考地 ...

  10. 2020-09-07:Docker的四种网络类型?

    福哥答案2020-09-07: 敲docker network ps命令,显示三种模式.1.bridge模式:使用–net =bridge指定,默认设置.桥接式网络模式(默认).容器的默认网络模式,d ...