干翻Mybatis源码系列之第八篇:Mybatis提供的缓存方案细节注意

news2024/12/24 8:22:14

前言

Mybatis缓存设计成了两层的体系,第一层叫做一级缓存,第二层叫做二级缓存(全局缓存)。我们从这里可以看到Mybatis的缓存方案是有两种处理方式的。

一级缓存(默认开启)
一级缓存默认开启的,程序首先去缓存中查找数据,缓存中没有的话再去数据库中进行查询。
二级缓存(全局缓存)

第一章:一级缓存

一:证明一级缓存默认开启

证明事项:
1:一级缓存默认开启
2:作为一级缓存来讲,只对于本SqlSession有效,别的SqlSession用不了。

二:换SqlSession更普遍

日后的开发过程中,这种换SqlSession是不是常见的呢?换的场景是普遍的,这是为什么呢?
不同的请求过来服务端之后,会有多个请求线程到达我们的服务端,Controler-Service-Dao,
Controller和Service和Dao都有可能是单例或者是多例的。这样的SqlSession是不一样的。

为什么说两个SqlSession是不一样的呢?这是为什么呢?我们开发过程中SqlSession也好,Conneciton也好是不能共享的,一定是一个请求一份。这是因为在开发过程中,这两个对象他是会控制事务的。正因为他们是控制事务的,才不能共享。

那么为什么控制事务的就不能共享呢?这是为什么呢?会产生相互的影响。假如说SqlSession是可以共享的,第一个线程开始事务啥也没干,第二个线程直接把事务提交了,这样不就有问题了么,所以这玩意是不可以共享的。

查询不是不需要事务么?这是不对的,查询在特殊场景下是需要事务的。这个特殊场景是在加悲观锁的时候,必须要事务。第二种说的就是我们二级缓存必须加事务,这样我们的二级缓存才会有效果。

那一般场景查询不是不需要事务的么?实际场景应用的时候,我们极少有只进行select的时候,更多的时候是一个Service把增删改查全干了。所以,这玩意必须要换,一个请求一个。

Mybatis一级缓存的作用和目的并没有那么大了,我们提供缓存的目的是为了是Java程序第二次与查询相同数据的时候可以从缓存中获取,减少与数据库之间的交互。提高系统效率,但是一级缓存如此设计的话,切换了SqlSession是用不上的。一级缓存在Mybatis设计当中对于我们开发帮助是不大的,主要解决的是Mybatis的内部的一些问题,内部比如说关联关系当中解决回环引用的时候使用的,对于应用来讲作用不大。

三:一级缓存源码分析

1:支持回顾

Mybatis通过如下:
sqlSession.getMapper()生成了UserDao的实现类。(代理实现类)
在代理底层调用的时候,实际上调用的是sqlSession.selectAll(),selectOne等方法,在这些方法里边是基于excutor方法来执行的。一级缓存和二级缓存的接入点都是在Excutor当中接入的。

Excutor接口实现类关系如下:

在这里插入图片描述
知识补充:

这个结构是一个典型的适配器设计模式。
适配器设计模式解决的是什么问题呢?
适配器就是变压器,适配器就是层层实现即可。一层实现一部分。
什么时候使用适配器模式?
我们这个类只想实现某些方法,将接口中的抽象方法进行分层实现。

在这里插入图片描述

2:源码分析

在这里插入图片描述
以及缓存当中的核心源码体现在哪里呢?是在BaseExcutor当中。子类都能享受到这个一级缓存的功能。

BaseExcutor当中维护了缓存,这个缓存到底是一个HashMap,两个PerpetualCache缓存一个是基本操作的缓存,一个是存储过程的缓存。存储过程是数据库的编程语言。数据库的变成语言专业名词就叫做存储过程,存储过程逐渐被大数据解决方案代替。

  protected PerpetualCache localCache;
  protected PerpetualCache localOutputParameterCache;

3:怎么接入缓存?

知识补充:
在这里插入图片描述

  @Override
  public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
    //拼接好的SQL
    BoundSql boundSql = ms.getBoundSql(parameter);
    //缓存Key
    CacheKey key = createCacheKey(ms, parameter, rowBounds, boundSql);
    //执行真正的查询
    return query(ms, parameter, rowBounds, resultHandler, key, boundSql);
 }
  @Override
  public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
    ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId());
    if (closed) {
      throw new ExecutorException("Executor was closed.");
    }
    if (queryStack == 0 && ms.isFlushCacheRequired()) {
      clearLocalCache();
    }
    List<E> list;
    try {
      queryStack++;
      list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;
      //有缓存查缓存
      if (list != null) {
        handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);
      //没缓存查数据库
      } else {
        list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
      }
    } finally {
      queryStack--;
    }
    if (queryStack == 0) {
      for (DeferredLoad deferredLoad : deferredLoads) {
        deferredLoad.load();
      }
      // issue #601
      deferredLoads.clear();
      if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {
        // issue #482
        clearLocalCache();
      }
    }
    return list;
  }
  private <E> List<E> queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
    List<E> list;
    localCache.putObject(key, EXECUTION_PLACEHOLDER);
    try {
      //查询数据库
      list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);
    } finally {
      localCache.removeObject(key);
    }
    //查询数据库之后放到缓存当中。
    localCache.putObject(key, list);
    if (ms.getStatementType() == StatementType.CALLABLE) {
      localOutputParameterCache.putObject(key, parameter);
    }
    return list;
  }

总结:
流程逻辑伴随着上述代码展开的,如果缓存中有数据直接返回,如果换出中没有数据为null,就查询数据库,查询数据库之后再将数据放到缓存当中便于下一次的查询。

第一次查询:
先做SQL-- 在做key–查询缓存–查询数据库–数据放到缓存中。
第二次查询:
先做SQL-- 在做key–查询缓存–直接返回数据。

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

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

相关文章

[天翼杯 2021]esay_eval

[天翼杯 2021]esay_eval <?php class A{ #定义一个名为A的类public $code ""; #定义一个公共属性code function __call($method,$args){ #call魔术方法 当调用一个不存在的成员方法的时候触发eval($this->code); #将code的值以php代码执行 }function __w…

c高级day3作业

#!/bin/bash # 脚本名称:myfirstshell echo hello hostname ls -a .. echo $PATH echo $HOME df -h id -g hostname echo goodbye #!/bin/bash a(ls -l /etc | grep "^-" ) #/etc文件中普通文件 b(ls -l /etc | grep "^d" ) #/etc文件中一级目录文件 …

一篇了解智慧网关

智慧网关是指基于互联网技术的智能网关&#xff0c;能够连接不同的物联网设备和传感器&#xff0c;实现数据采集、信息传递、远程控制、通信管理等功能。作为物联网架构中的核心设备之一&#xff0c;智慧网关在智能家居、智慧城市、智能制造、智能交通、智能农业等领域得到了广…

solidworks三维建模竞赛练习题

solidworks三维建模竞赛练习题&#xff1a;3D01‐ 01 solidworks三维建模竞赛练习题&#xff1a;3D01‐ 02 solidworks三维建模竞赛练习题&#xff1a;3D01‐ 03 solidworks三维建模竞赛练习题&#xff1a;3D01‐ 04 solidworks三维建模竞赛练习题&#xff1a;3D01‐ 05 solidw…

windows docker 创建mysql主从 容器创建mysql主从

1. docker命令新建mysql-master&#xff0c;只是简单测试&#xff0c;没有设置映射&#xff0c;只是验证主从连接&#xff0c;需要可自行添加 docker run --restartalways --name mysql-master --privilegedtrue -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD123456 mysql:8.0 2.…

Linux - 第11节 - 网络入门

目录 1.计算机网络背景 1.1.网络发展 1.2.认识 "协议" 2.网络协议初识 2.1.协议分层 2.2.OSI七层模型 2.3.TCP/IP五层&#xff08;或四层&#xff09;模型 3.网络传输基本流程 3.1.同局域网的两台主机通信 3.2.跨网络的两台主机通信 1.计算机网络背景 1.1…

spring事务报错Transaction rolled back because it has been marked as rollback-only

之前经常报"Transaction rolled back because it has been marked as rollback-only"这个异常 字面意思是"事务回滚了&#xff0c;因为它被标记了必须回滚"&#xff0c;最开始完全不懂事务的嵌套&#xff0c;每次出现这个错误都想知道为什么&#xff0c;但…

套接字类型和协议设置

创建套接字 成功返回文件描述符&#xff0c;失败返回-1 int socket (int __domain, int __type, int __protocol) ;__domain&#xff1a;套接字中使用的协议族信息 一般使用PF_INET&#xff08;IPv4互联网协议族&#xff09;&#xff0c;其它协议族不常使用或尚未普及。另外&a…

算法设计与分析:大整数的加减乘除运算

目录 任务描述 相关知识 大整数的思想 大整数加法 大整数减法 大整数与整数的乘法 大整数乘法 大整数与整数的除法 n的阶乘求解思路 编程要求 测试说明 任务描述 本关任务&#xff1a;掌握大整数的基本思想&#xff0c;并运用大整数的基本运算计算出常规整数n的阶乘…

seaweedfs服务启动参数及翻译(seaweed参数、seaweed命令、weed参数、weed命令)(在单个容器同时启动master、volume、filer服务)

文章目录 weed命令翻译weed server命令翻译 weed filer命令 docker容器运行示例&#xff08;docker run命令&#xff09;以下是一个在单个容器启动master、volume、filer服务的示例 weed server 容器debug 版本&#xff1a;3.47从官方镜像docker容器里扒下来的&#xff0c;只扒…

【多线程】单例模式

目录 饿汉模式 懒汉模式-单线程版 懒汉模式-多线程版 懒汉模式-多线程版(改进) 单例是一种设计模式。 啥是设计模式 ? 设计模式好比象棋中的 " 棋谱 ". 红方当头炮 , 黑方马来跳 . 针对红方的一些走法 , 黑方应招的时候有一些固定的套路. 按照套路来走局势…

5.11 C高级作业

编写一个名为myfirstshell.sh的脚本&#xff0c;它包括以下内容。 1、包含一段注释&#xff0c;列出您的姓名、脚本的名称和编写这个脚本的目的 2、和当前用户说“hello 用户名” 3、显示您的机器名 hostname 4、显示上一级目录中的所有文件的列表 5、显示变量PATH和HOME的…

高性能网络 SIG 月度动态:长期投入得到业界认可,新增一位 virtio reviewer

高性能网络 SIG&#xff08;Special Interest Group&#xff09; &#xff1a;在云计算时代&#xff0c;软硬件高速发展&#xff0c;云原生、微服务等新的应用形态兴起&#xff0c;让更多的数据在进程之间流动&#xff0c;而网络则成为了这些数据流的载体&#xff0c;在整个云时…

Hive概述和安装

hive简介 Hive&#xff1a;由Facebook开源用于解决海量结构化日志的数据统计工具。 Hive是基于Hadoop的一个数据仓库工具&#xff0c;将结构化的数据文件映射为一张表&#xff0c;并提供类SQL(HQL)查询功能。 Hive本质&#xff1a;将HQL转化成MapReduce程序 &#xff08;1&am…

无锁队列实现及使用场景

写在前面 在看无锁队列之前&#xff0c;我们先来看看看队列的操作。队列是一种非常重要的数据结构&#xff0c;其特性是先进先出&#xff08;FIFO&#xff09;&#xff0c;符合流水线业务流程。在进程间通信、网络通信间经常采用队列做缓存&#xff0c;缓解数据处理压力。根据…

device_node转换成platform_device

device_node转换成platform_device 文章目录 device_node转换成platform_device转换规则主要核心函数of_default_bus_match_tablearmarm64of_platform_register_reconfig_notifier Linux内核是如何将device_node转换成platform_deviceof_platform_populate函数处理根节点下的子…

在ubuntu连接Xlight FTP Server

一 在windows上搭建服务器 http://www.xlightftpd.com/download.htm 使用英文版&#xff0c;使防止在ubuntu中登录中文版时&#xff0c;显示乱码 新建用户和用户对应的服务器目录 如下所示&#xff0c;默认只有读权限 全都勾选 勾选完毕后的效果 在目录中放一个文件&#…

10款常用的原型设计工具,包含一键生成原型工具

原型图是产品设计师日常工作的“常客”&#xff0c;原型图软件也扮演着产品设计师的“武器”角色。 许多新产品设计师不知道如何选择原型图软件。本文盘点了10个优秀的原型图软件&#xff0c;让我们来看看。 1.即时设计 即时设计是一款免费的在线 UI 设计工具&#xff0c;无…

【Java数据结构】排序

排序 插入排序希尔排序选择排序堆排序冒泡排序快速排序序列的分割Hoare法挖坑法快慢指针法 优化1 - 三数取中优化2- 数据规模小时的插入 归并排序 插入排序 直接插入排序是一种简单的插入排序法&#xff0c;其基本思想是&#xff1a; 把待排序的记录按其关键码值的大小逐个插…

Jetson Orin环境安装Opencv+Cuda以及vscode环境配置

文章目录 一&#xff1a;Opencv Cuda源码的下载、编译1.卸载jetson上自带的无cuda加速Opencv2.安装Opencv依赖库3.下载 OpenCV 和 opencv_contrib 源码4.编译安装 OpenCV、opencv_contrib 二&#xff1a;Opencv 的环境配置三&#xff1a;Vscode 中的Opencv环境配置四&#xff…