【框架】MyBatis 框架重点解析

news2024/11/15 15:40:53

MyBatis 框架重点解析

1. MyBatis 执行流程

在这里插入图片描述

会话工厂生产的 SqlSession 对象提供了对数据库执行SQL命令所需的所有方法,包括但不限于以下功能:

  1. 数据库操作:SqlSession可以执行查询(select)、插入(insert)、更新(update)、删除(delete)等各种SQL命令,从而实现对数据库的CRUD操作。
  2. 事务管理:SqlSession可以开始、提交或回滚事务,确保多个数据库操作可以作为一个原子操作进行。
  3. 对象映射:SqlSession可以将查询结果映射为Java对象,简化了数据的处理和转换过程。
  4. 缓存管理:SqlSession可以管理MyBatis的一级缓存和二级缓存,提高数据库访问性能。
  5. 执行存储过程:SqlSession可以执行数据库中的存储过程,并获取其返回结果。

每个 SqlSession 就代表一次数据库连接和一个 Mapper 中的方法,也管理着对应的对象映射,并且执行完应该断开连接,是个生命周期很短的对象;

MappedStatement 优点类似与之前 JDBC 的准备态对象,底层也确实是 JDBC;

完整流程:

在这里插入图片描述

回答:

  1. 读取 MyBatis 相关配置:
    1. 全局设置,mybatis-config.xml 文件加载运行环境,当然很多时候,会在包路径下的 yaml 文件中配置(yaml 配置作用的是 Bean 对象,要用 Mapper,需要配置启动类的扫描包路径);
    2. 映射文件,XXXMapper.xml 文件,编写了具体的SQL映射语句的文件,每个Mapper接口通常会对应一个Mapper.xml文件,其中定义了SQL语句的映射关系、动态SQL等内容。
  2. 构建会话工厂 SqlSessionFactory,全局一个;
  3. 当进行一次操作的时候,会话工厂创建 SqlSession 对象(包含了执行 SQL 语句的所有方法,有了这些基础的方法,才能执行 SQL,并正确处理参数与返回值);
  4. 而创建 SqlSession 需要一个 MappedStatement 类型的对象,它封装了映射信息与预执行 SQL 等信息;
    • 这个对象在一开始读取 MyBatis 相关配置的时候就创建了,根据不同的 sql 的 ID 来区分;
  5. 然后调用操作数据库的接口 Executor 执行器,同时负责查询缓存的维护;
  6. 输入参数映射,获得真实执行的 SQL 语句 ,执行 SQL 命令并获取结果;(根据 MappedStatement)
  7. 输出结果映射,将数据库返回的结果集映射成 Java 对象;(根据 MappedStatement)
  8. 提交会话(flush) / 断开数据库连接(close)(也有可能放入数据库连接池,保持数据库连接);

当我们属性注入 Mapper 后,前 5 步就已经完成了;

2. MyBatis 是否支持延迟加载(懒加载)?

  • 延迟加载的意思就是:需要某个数据的时候再加载,不需要用到数据时则不加载,是一种懒汉模式;

  • MyBatis 支持一对一关联对象和一对多关联集合对象的延迟加载;

    在这里插入图片描述

    像这种,一个结果集中的某个属性,是通过另一条 sql 获得的(如果是多表查询的一条 sql 就不会涉及多 sql);

    这样的场景,就可以用延迟加载;

  • 这个延迟加载默认是关闭的,如果要开启则需要以下配置:

    1. 在 mybatis-config.xml / xml 中的结果集定义中启动延迟加载:

    全局:

    在这里插入图片描述

    针对某一个:

    在这里插入图片描述

    <resultMap id="userResultMap" type="User">
      <id property="id" column="id" />
      <result property="username" column="username" />
      <association property="department" column="dept_id" select="selectDepartmentById" lazyLoadingEnabled="true"/>
    </resultMap>
    
    1. yaml 配置:

      全局:

      mybatis:
        configuration:
          default-lazy-loading-enabled: true
      

      针对某一个:

      mappers:
        - name: YourMapperName
          delayLoading: true
      

3. MyBatis 延迟加载的底层原理是什么?

在这里插入图片描述

  1. 返回的不仅仅是一个 Java 对象,而是 CGLIB 创建的目标对象增强后的代理对象(简单地理解为受监视的对象,被代理的对象);

  2. 当代理对象用到 orderList 的时候,即调用 getOrderList() 的时候;

  3. orderList 如果是 null,则代表未加载/未被设置,则会执行 sql 查询并通过 setter 方法设置到 orderList 属性上,并继续执行 getOrderList() 方法;

  4. 之后代理对象中 orderList 是有值的,就不需要进行 SQL 查询了;(如果查询结果本来就是 null,那确实会每次 get 都进行 SQL 查询,但是一般不会反复 get,如果真的有对应的场景就可能有性能问题,可能需要换一个加载策略);

4. MyBatis 的一级、二级缓存用过吗?

在这里插入图片描述

4.1 一级缓存

  • 同一个 sqlSession,同一个 sql 输入参数一致,就走缓存;

在这里插入图片描述

4.2 二级缓存

  • 同一个 namespace 和 mapper 的作用域(一个 Mapper 映射文件 ),同一个 sql 输入参数一致,就走缓存;

在这里插入图片描述

4.3 配置

一级缓存是默认打开的,二级缓存是默认关闭的,以下是配置方法:

# mybatis-config.yml

# 配置一级缓存
configuration:
  localCacheScope: SESSION # 可选值为 SESSION(默认)和 STATEMENT

# 配置二级缓存
environments:
  default:
    cache:
      type: org.apache.ibatis.cache.impl.PerpetualCache # 使用 PerpetualCache 作为二级缓存的实现
      eviction: LRU # 可选值为 LRU, FIFO, SOFT, WEAK, NONE
      flushInterval: 60000 # 刷新缓存的时间间隔,单位为毫秒
      size: 1024 # 缓存的最大条目数

或者是 mybatis-config.xml 配置的方式:

在这里插入图片描述

记得,还需要在要打开二级缓存的映射文件中,去加个 <cache /> 标签,声明打开二级缓存;

在这里插入图片描述

4.4 注意事项

  1. 对于缓存刷新机制,当一个作用域内(sqlSession / namespace),进行了增删改操作,默认该作用域下的所有 select 的缓存将被 clear;
    • 你可能会想,微服务开发怎么办?但是微服务的 MyBatis 在合理开发是不会重用的,而是访问别的微服务,所以对于同一个域仍然在同一个微服务去执行;
  2. 二级缓存需要缓存的数据要实现 Serializable 接口;
  3. 数据不会直接进入二级缓存,而是会话提交或者关闭以后,一级缓存中的数据才会序列化转移到二级缓存中;

4.5 回答

  1. 一级缓存:基于 PerpetualCache 的 HashMap 本地缓存,其存储作用域是 Session,当 Session 进行 flush 或者 close 之后,该 Session 中的 Cache 就将清空,默认打开;
  2. 二级缓存:基于 namespace 和 mapper 的作用域起作用域,不依赖于 SqlSession,默认也是采用 PerpetualCache 的 HashMap 存储。默认关闭,需要配置开启,一个是 yaml / 核心配置文件,一个是需要打开二级缓存的 mapper 映射文件;

MyBatis 的二级缓存什么时候会清楚缓存中的数据:

  • 当一个作用域内(sqlSession / namespace),进行了增删改操作,默认该作用域下的所有 select 的缓存将被 clear;

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

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

相关文章

桥接模式(Bridge Pattern) C++

上一节&#xff1a;适配器模式&#xff08;Adapter Pattern&#xff09; C 文章目录 0.理论1.组件2.使用场景 1.实践 0.理论 桥接模式&#xff08;Bridge Pattern&#xff09;是一种结构型设计模式&#xff0c;它的核心思想是将抽象部分与其实现部分分离&#xff0c;使它们可…

liunx安装jdk、redis、nginx

jdk安装 下载jdk,解压。 sudo tar -zxvf /usr/local/jdk-8u321-linux-x64.tar.gz -C /usr/local/ 在/etc/profile文件中的&#xff0c;我们只需要编辑一下&#xff0c;在文件的最后加上java变量的有关配置&#xff08;其他内容不要动&#xff09;。 export JAVA_HOME/usr/l…

操作系统系列学习——多进程图像

文章目录 前言多进程图像 前言 一个本硕双非的小菜鸡&#xff0c;备战24年秋招&#xff0c;计划学习操作系统并完成6.0S81&#xff0c;加油&#xff01; 本文总结自B站【哈工大】操作系统 李治军&#xff08;全32讲&#xff09; 老师课程讲的非常好&#xff0c;感谢 【哈工大】…

设置文字之间的间距应该如何实现

设置文字之间的间距&#xff0c;通常指的是字母之间&#xff08;字符间距&#xff09;或单词之间的间距。在CSS中&#xff0c;这可以通过letter-spacing和word-spacing属性来实现。 字符间距&#xff08;letter-spacing&#xff09; letter-spacing属性用于调整字符之间的间距…

【Kotlin】函数

1 常规函数 1.1 无参函数 fun main() {myFun() }fun myFun() {println("myFun") // 打印: myFun } 1.2 有参函数 1&#xff09;常规调用 fun main() {myFun("myFun") // 打印: myFun }fun myFun(str: String) {println(str) } 2&#xff09;形参指定默…

C++:设计包含min 函数的栈

目录 题目 代码实现 输出 题目 定义栈的数据结构&#xff0c;要求添加一个min 函数&#xff0c;能够得到栈的最小元素。 要求函数min、push 以及pop 的时间复杂度都是O(1)。 代码实现 #include <iostream>template<typename T>class stack { public:stack() {…

React富文本编辑器开发(四)

上一节我们做了块级元素的格式操作&#xff0c;这节我们来讲行内元素的相关操作。行内元素的样式一般指 粗体、斜体、代码或 删除线等 。通过前一章的内容得知&#xff0c;元素的渲染是通过渲染器来呈现的&#xff0c;块级元素通过指定 renderElement, 行内元素&#xff08;即内…

vxe-table编辑单元格动态插槽slot的使用

业务场景&#xff1a;表格中只有特定某一行的的单元格可以编辑&#xff0c;列很多&#xff0c;为每个列写个插槽要写很多重复代码&#xff0c;所以这里使用动态插槽&#xff0c;简化代码量。显示编辑图标&#xff0c;点击编辑图标隐藏。失去焦点保存调后台接口。 解决办法&…

【C语言】文件及文件操作详解(fseek,ftell,rwind)

目录 1. 为什么使用文件 2. 什么是文件 2.1 程序文件 2.2 数据文件 2.3 文件名 3. 二进制文件和文本文件 4. 文件的打开和关闭 4.1 流和标准流 4.1.1 流 4.1.2 标准流 4.2 文件指针 4.3 文件的打开和关闭 5. 文件的顺序读写 6.文件的随机读写 6.1 fseek 6.2 ft…

解决Keepalived “脑裂”(双VIP)问题

1. 检查广播情况 yum install tcpdump -y tcpdump -i ens33 vrrp -n master 192.168.80.130 与 backup: 192.168.80.131都在广播&#xff0c;正常情况下backup应该是不在广播的&#xff0c;所以可以判断存在防火墙屏蔽vrrp问题&#xff0c;需要设置VRRP过掉防火墙&#xff0…

浏览器常见问题及技巧总结-------( 更新中 )

浏览器常见问题及技巧总结 浏览器1 查找网页关键字2 如何利用技术下载网上图片3 百度搜索技巧 待续、更新中 浏览器 1 查找网页关键字 火狐firefox Ctrlf: 在网页中查找关键字2 如何利用技术下载网上图片 插件: 图片助手(但还是有水印, 比起原版的要差些)3 百度搜索技巧 1.…

SpringCloud gateway限流无效,redis版本低的问题

在使用springCloud gateway的限流功能的时候&#xff0c;配置RedisRateLimiter限流无效&#xff0c;后来发现是Redis版本过低导致的问题&#xff0c;实测 Redis版本为3.0.504时限流无效&#xff0c;改用7.0.x版本的Redis后限流生效。查了资料发现很多人都遇见过这个问题&#x…

【网站项目】314学生二手书籍交易平台

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

直流电压变送器更改从站地址

直流电压变送器采集模块转RS485修改地址 产品图片 产品说明书 修改从站地址 在串口助手上将默认的从站地址01h修改为0Bh 原从站地址&#xff1a;01h 修改参数&#xff1a;10h 通信参数允许修改寄存器&#xff1a;1b fe&#xff08;说明书里7166的十六进制&#xff09; 00 02…

c语言的数据结构:队列

1.队列存在的实现方式及其存在意义 1.1为什么队列使用单链表实现更好 动态内存分配&#xff1a;链表在C语言中通常使用动态内存分配&#xff0c;这意味着可以在运行时根据需要动态地添加或删除节点。这对于实现一个动态大小的队列非常有用&#xff0c;因为队列的大小可以在运…

Matlab在同一张图中如何加入多个图例

根据代码最终画出的图片如下&#xff1a; 其实原理很简单&#xff0c;就是在一张figure中画多个坐标轴&#xff0c;每个坐标轴都有对应的图例&#xff0c;之后再将多余坐标轴隐藏&#xff0c;只保留一个即可。 代码如下&#xff1a; clear all; close all;dd_linewidth 1;a …

2024广东水展即将开幕 | 聚焦净水行业热点抢占行业新机遇

2024广东水展即将开幕 | 聚焦净水行业热点抢占行业新机遇 随着消费升级和人们对环境健康的意识增强&#xff0c;人们除了关注净水产品的性能外&#xff0c;对产品的设计、服务、多应用场景化等需求也愈发多样化。节能环保、智能化成为产品迭代升级主要方向。据奥维云网数据显示…

二叉搜索树的范围和(Lc938)——DFS

给定二叉搜索树的根结点 root&#xff0c;返回值位于范围 [low, high] 之间的所有结点的值的和。 示例 1&#xff1a; 输入&#xff1a;root [10,5,15,3,7,null,18], low 7, high 15 输出&#xff1a;32示例 2&#xff1a; 输入&#xff1a;root [10,5,15,3,7,13,18,1,nul…

分享Selenium测试工具用来模拟用户浏览器的操作

执行JS的类库&#xff1a;execjs&#xff0c;PyV8&#xff0c;selenium&#xff0c;node pip list pip install selenium pip install xlrd pip install xlwt pip install PyExecJS pip install xlutils selenium测试工具可以用来模拟用户浏览器的操作&#xff0c;其支持的浏览…

使用lnmp环境部署laravel框架需要注意的点

1&#xff0c;上传项目文件后&#xff0c;需要chmod -R 777 storage授予文件权限&#xff0c;不然会报错file_put_contents(/): failed to open stream: Permission denied。 如果后面还是报错没有权限的话&#xff0c;就执行ps -ef |grep php查询php运行用户。然后执行chown …