算不上最全,但都是必备——Mybatis这些不会不行啊

Mybatis篇

ORM(Object Relational Mapping),对象关系映射,是一种为了解决关系型数据库数据与简单Java对象(POJO)的映射关系的技术。简单的说,ORM是通过使用描述对象和数据库之间映射的元数据,将程序中的对象自动持久化到关系型数据库中。

为什么使用代理对象来执行 SQL 语句

在 MyBatis 中,数据操作通常由 Mapper 接口和 XML 配置文件来实现。当 MyBatis 执行一个 Mapper 接口方法时,它首先会根据 Mapper 接口方法名、方法参数等信息,查找对应的 SQL 语句,并执行这条 SQL 语句。而这个 SQL 语句是通过 MyBatis 在后台动态创建的,生成过程包括了 SQL 语句的拼装、参数的设置等步骤。

MyBatis 为了记录和跟踪 SQL 执行过程,需要在调用 Mapper 接口方法时动态生成这个代理对象,这个代理对象可以拦截 Mapper 接口方法的调用,并记录 SQL 执行的相关信息。同时,代理对象还可以通过调用底层 SQL 执行 API,将生成的 SQL 语句和参数传递给底层数据库操作来实现数据访问

另外,使用代理对象还可以提供更好的灵活性。如果直接使用普通对象进行操作,一个对象只能对应一条 SQL 语句,而代理对象可以根据配置动态生成多条 SQL 语句,并对传入的参数进行动态调整,因此提供了更强的灵活性和扩展性。


MyBatis执行流程

  • 读取MyBatis配置文件:mybatis-config.xml加载运行环境和映射文件
  • 根据读取到的配置信息,MyBatis 构建一个 SqlSessionFactory 对象
  • 会话工厂创建 SqlSession 对象(包含了执行SQL语句的所有方法)它负责管理数据库连接、执行SQL语句、提交或回滚事务等。
  • 操作数据库的接口 ExecutorSqlSession 中的方法实际上是由 Executor 执行器来执行的。Executor 负责管理数据库连接、执行 SQL 语句,并维护查询缓存。
  • Executor接口的执行方法中有一个MappedStatement类型的参数,它封装了 SQL 语句的映射信息。MappedStatement 包含了 SQL 语句、参数映射、结果映射等相关配置。
  • 输入参数映射,当执行 SQL 语句时,MyBatis 可以将传入的 Java 对象与 SQL 语句中的参数进行映射,从而方便地传递参数给 SQL 语句。
  • 输出结果映射,在执行查询操作时,MyBatis 将查询结果映射到指定的 Java 对象中。这可以通过配置或注解来指定结果集resultMap与 Java 对象之间的映射关系。

image.png


MyBatis 延迟加载

Mybatis支持延迟记载,但默认没有开启

什么叫做延迟加载?

MyBatis 的延迟加载是指在使用一条SQL查询语句获取对象时,并不立即加载该对象关联的其他对象或属性,而是在真正需要使用这些关联对象或属性时,才发起相应的 SQL 查询加载。这种方式可以有效地减少不必要的数据库查询,提高系统性能。

<resultMap id="userResultMap" type="User">
  <id column="id" property="id"/>
  <result column="username" property="username"/>
  <collection property="orderList" ofType="order"
              select="com.itheima.mapper.OrderMapper.findByUid"      // 关联查询的mapper函数
              column="id">              
  </collection>
</resultMap>
​
<select id="getUser" resultMap="userResultMap">
      select 
            * 
      from 
            t_user
      where 
            id = #{id}
</select>

对于以上这个SQL,由于其未设置延迟加载操作,所以当调用 getUser()函数的时候,就会夹带 OrderMapper.findByUid 函数一起查询用来获取当前封装类的关联对象列表数据,所以说会执行两端SQL,但是是实际上,有时候我们只需要拿到用户相关的数据就行,不必要将其的订单数据也查询出来返回,如果我们采用了延迟加载,当我们在用到最终封装类中的订单的数据板块的时候,才会去执行获取订单数据的这么段SQL,反之是不会执行的,这样子就避免了额外的资源消耗。

延迟加载的原理

  • 使用CGLIB创建目标对象的代理对象
  • 当调用目标方法user.getOrderList()时,被拦截器拦截,进入拦截器invoke方法,发现user.getOrderList()是null值,执行sql查询order列表
  • 把order查询上来,然后调用user.setOrderList(List orderList) ,接着完成user.getOrderList()方法的调用

image.png

延迟加载实现

全局延迟
mybatis.configuration:
  lazy-loading-enabled: true  # 开启全局延迟加载
  aggressive-lazy-loading: true # 延迟加载的层次深度
  proxy-factory: JAVASSIST  # 延迟加载时用的代理类型
局部延迟
<resultMap id="userResultMap" type="User">
  <id column="id" property="id"/>
  <result column="username" property="username"/>
  <collection property="orderList" ofType="order"
              select="com.itheima.mapper.OrderMapper.findByUid"         // 关联查询的mapper函数
              column="id" fetchType="lazy">              // 针对该对象关联的其他对象列表进行延迟加载
  </collection>
</resultMap>
​
<select id="getUser" resultMap="userResultMap">
  select 
    * 
  from 
    t_user
  where 
    id = #{id}
</select>

延迟加载的弊端

  • 增加额外的查询次数。 当使用延迟加载时,需要在要使用关联对象时对该对象进行查询,这样会增加额外的查询次数,从而影响了系统的响应速度。
  • 增加内存消耗。 在延迟加载的情况下,每加载一个对象就会增加一个对象的内存消耗,如果同时加载多个对象,就会增加大量的内存消耗,从而影响系统的性能。
  • 可能导致 N+1 查询问题。 当使用延迟加载时,会出现 N+1 查询问题,即在查询一个对象时,需要先查询主对象,然后再查询关联对象,这样就会导致 N+1 个查询,从而影响系统的性能

Mabatis 缓存

Mabatis缓存主要包含一级缓存和二级缓存两种,二者都是基于 PerpetualCache 的 HashMap 本地缓存

在 MyBatis 中,缓存的实现是以 CacheKey 对象为 key,查询结果为 value 保存在缓存中的。CacheKey 对象是一个复合键,它包含了执行语句的 id、查询参数等信息,以保证相同的语句执行以及相同参数的查询能返回同样的结果。

一级缓存

一级缓存: 基于 PerpetualCache 的 HashMap 本地缓存 (存储在内存中) ,其存储作用域为 Session ,当Session进行flush或close之后,该Session中的所有Cache就将清空,默认一级缓存是打开的(这里的Session是SqlSession,不是前后端交互的Session)

image.png

二级缓存

二级缓存(全局缓存)是基于 namespacemapper 的作用域起作用的,所有的 SqlSession 对象共享同一个缓存,默认也是采用 PerpetualCache,HashMap 存储 (存储在本地外存持久文件中)

image.png

二级缓存默认是关闭

开启方式

  1. 全局配置文件

image.png

  1. 映射文件Mapper.xml上加上标签让当前mapper生效二级缓存

实现原理

一级缓存的实现原理

在 SqlSession 里面持有一个 Executor,每个 Executor 中有一个 LocalCache 对象。当用户发起查询的时候,Mybatis 会根据执行语句在 Local Cache 里面查询,如果没命中,再去查询数据库并写入到 LocalCache,否则直接返回。

image.png

二级缓存的实现原理

使用 CachingExecutor 装饰了 Executor,所以在进入一级缓存的查询流程前,会先通过 CachingExecutor 进行二级缓存的查询。开启二级缓存以后,会被多个 SqlSession 共享,所以它是个全局缓存。因此它的查询流程是先查二级缓存,再查一级缓存,最后再查数据库

image.png

注意点

  • 对于缓存数据更新机制,当某一个作用域进行了事务操作后,默认该作用域下所有 select 中的缓存将被 clear
  • 只有会话提交或者关闭以后,一级缓存中的数据才会转移到二级缓存中
  • 使用了二级缓存后,先查二级缓存,再查一级缓存,最后再查数据库
  • 二级缓存从缓存中移除某个对象的淘汰算法。默认采用LRU策略。可以设置定期清除
  • MyBatis 的二级缓存相对于一级缓存来说,实现了 SqlSession 之间缓存数据的共享,同时缓存粒度也能够到 namespace 级别,并且还可以通过 Cache 接口实现类不同的组合,对 Cache 的可控性也更强
  • MyBatis 的一级缓存中,缓存的数据是存储在内存中的,并不需要进行序列化和反序列化操作。因此,针对一级缓存的封装类不需要实现 Serializable 接口;对于 MyBatis 的二级缓存,缓存的数据是存储在持久化介质(如文件、数据库等)上的,所以需要进行序列化和反序列化操作。
  • 一级缓存,在多个 Sqlsession 或者分布式环境下,可能会导致数据库写操作出现脏数据。 (联系主存和工作内存的知识)

Mybatis 中#{}和${}的区别

Mybatis 提供到的#号占位符和$号占位符,都是实现动态 SQL 的一种方式,通过这两种方式把参数传递到 XML 之后

  • # 号占位符它相当于向 PreparedStatement 中的预处理语句中设置参数,而 PreparedStatement 中的 sql 语句是预编译的,SQL 语句中使用了占位符,规定了sql 语句的结构,并且在设置参数的时候,如果有特殊字符,会自动进行转义。所以#号占位符可以防止 SQL 注入
  • 使用 $ 的方式传参,相当于直接把参数拼接到了原始的 SQL 里面,Mybatis不会对它进行特殊处理。有SQL 注入的风险

所以$和#最大的区别在于,前者是动态参数,后者是占位符, 动态参数无法防止 SQL注入的问题,所以在实际应用中,应该尽可能的使用#号占位符。

另外,$符号的动态传参,可以适合应用在一些动态 SQL 场景中,比如动态传递表名、动态设置排序字段等。

SQL注入是攻击者通过插入恶意的SQL代码欺骗应用程序,可能导致数据泄露、数据库破坏和应用程序完全被控制。预防方法包括过滤和转义输入参数、使用参数化查询、实施权限和访问控制,并加强安全意识和防范措施。


Mybatis 分页操作

  • Interceptor 拦截器实现,通过拦截需要分页的 select 语句,然后在这个 sql 语句里面动态拼接分页关键字,从而实现分页查询。

image.png

分页插件的基本原理是什么?

当 MyBatis 创建一个代理对象来执行 SQL 语句时,会使用 JDK动态代理机制。通过动态代理,它会创建一个代理对象,这个代理对象可以拦截目标类的方法调用,并在方法执行前后做一些额外的处理。

对于分页插件来说,它会拦截 Executor 接口的 query 方法。在 query 方法前后,分页插件会先获取分页参数(如页码、每页记录数等),然后根据这些参数动态生成对应的分页 SQL 语句。

责任链设计模式用于实现分页插件的拦截器链。在 MyBatis 中,通过实现 Interceptor 接口,并将拦截器按照顺序添加到拦截器链中,就可以形成一个责任链。当 MyBatis 执行 SQL 语句时,会按照添加拦截器的顺序,依次调用每个拦截器的 intercept 方法。每个拦截器可以在此方法中进行一些前置或后置处理,然后再传递给下一个拦截器。分页插件就是通过拦截器链实现了对 SQL 语句的拦截和修改。

通过 JDK 动态代理和责任链设计模式的结合使用,MyBatis 分页插件能够灵活地拦截并修改 SQL 语句,以实现分页功能。


MyBatis中接口绑定的原理

MyBatis 中接口绑定的原理是通过JDK动态代理实现的。

在 MyBatis 中,接口绑定是指将 Mapper 接口与对应的 XML 配置文件进行关联,实现接口方法与 SQL 语句的映射。这样,我们就可以通过调用接口方法来执行对应的 SQL 操作。

当我们在应用程序中调用 Mapper 接口的方法时,MyBatis 会通过动态代理机制来实现接口方法的调用。它会生成一个实现了该接口的代理对象,并注册到 SqlSession 的 Configuration 对象中。

在代理对象的方法调用过程中,MyBatis 会首先通过 Configuration 对象找到与方法名对应的 MappedStatement 对象,MappedStatement 包含了 SQL 语句的配置信息。然后,MyBatis 将通过 SqlSession 调用相应的 SQL 执行方法,并将 MappedStatement 对象和方法参数传递给底层的 SQL 执行引擎。

使用动态代理的好处是,它可以在不修改原始接口代码的情况下,通过注入逻辑来增强接口的功能。在 MyBatis 中,我们通过在 XML 配置文件中编写对应的 SQL 语句,实现了将接口方法与 SQL 语句的映射关系,从而进行数据访问操作。

总结起来,MyBatis 的接口绑定通过动态代理实现。它通过生成接口的代理对象,在接口方法调用时根据配置文件的映射关系执行对应的 SQL 语句,实现了接口方法与 SQL 的绑定。这种设计方式使得开发者可以在接口层面上进行业务操作,简化了数据访问代码的编写和维护。


Mybatis的预编译

当使用 MyBatis 进行 SQL 操作时,默认情况下,每次执行 SQL 语句时,MyBatis 都会将 SQL 语句发送给数据库进行解析、编译和执行。这个过程需要消耗时间和资源。

为了优化 SQL 执行的效率,MyBatis 引入了预编译的机制。预编译指的是将 SQL 语句提前编译好,并缓存到内存中以供重复使用。这样,在下一次执行相同的 SQL 语句时,MyBatis 就可以直接使用缓存的编译结果,而不需要再次进行解析和编译过程。

具体来说,当使用 MyBatis 进行 SQL 操作时,我们可以通过在 Mapper XML 文件中使用占位符或 #{} 表达式来构建 SQL 语句。MyBatis 在执行 SQL 语句之前,会将占位符替换为具体的参数值,并将最终生成的 SQL 语句缓存到内存中。下一次如果执行相同的 SQL 语句,MyBatis 就可以直接使用缓存的编译结果。

这里的关键是,MyBatis 会将执行后的 SQL 语句预编译并缓存到内存中。下一次如果我们再次调用相同的 SQL 语句,只需要传递不同的参数值,MyBatis 将直接使用缓存的编译结果,而不需要再进行解析和编译的过程。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

天气越来越寒冷,一定要注意保暖

你们那里下雪了吗&#xff1f;听说西安已经下了今年的第一场雪&#xff0c;我们这里虽然隔了几百公里&#xff0c;但是只下雨没有下雪&#xff0c;不过气温是特别的冷&#xff0c;尤其是对我们这些上班族和上学的人而言&#xff0c;不管多冷&#xff0c;不管刮风下雨&#xff0…

根据店铺ID或店铺昵称或店铺链接获取阿里巴巴店铺所有商品数据接口|阿里巴巴店铺整店商品数据接口|阿里巴巴API接口

阿里巴巴店铺所有商品数据接口是阿里巴巴开放平台提供的API接口之一&#xff0c;它可以帮助开发者获取到店铺内所有商品的信息&#xff0c;包括商品的ID、标题、价格、图片、链接等。通过该接口&#xff0c;开发者可以快速地获取到大量的商品数据&#xff0c;并进行进一步的数据…

自定义注解实现服务的动态开关

shigen日更文章的博客写手&#xff0c;擅长Java、python、vue、shell等编程语言和各种应用程序、脚本的开发。记录成长&#xff0c;分享认知&#xff0c;留住感动。 &#x1f9d1;‍&#x1f4bb;&#x1f9d1;‍&#x1f4bb;&#x1f9d1;‍&#x1f4bb;Make things differe…

matlab语言的由来与发展历程

MATLAB语言的由来可以追溯到1970年代后期。当时&#xff0c;Cleve Moler教授在New Mexico大学计算机系担任系主任&#xff0c;他为了LINPACK和EISPACK两个FORTRAN程序集开发项目提供易学、易用、易改且易交互的矩阵软件而形成了最初的MATLAB。 1984年&#xff0c;MATLAB推出了…

JVM 内存区域

JVM内存结构模型 程序计数器&#xff1a; 1.线程私有的&#xff0c;是一块较小的内存空间&#xff0c;当前线程所执行的字节码的行号指示器 2.每个线程都有一个独立的程序计数器&#xff0c;各线程之间程序计数器互不影响&#xff0c;独立存储 3.此内存区域是唯一一个在java虚拟…

C++ vector中capacity()和size() 的区别

文章目录 1 capacity()和size() 介绍2 vector满了之后&#xff0c;capacity()会自动了扩充为原来的2倍 &#xff1f; 1 capacity()和size() 介绍 size是指容器当前拥有元素的个数&#xff0c; capacity是指容器在必须分配新的存储空间之前可以存放的元素总数。 如vector<i…

Linux常用命令——bzgrep命令

在线Linux命令查询工具 bzgrep 使用正则表达式搜索.bz2压缩包中文件 补充说明 bzgrep命令使用正则表达式搜索“.bz2”压缩包中文件&#xff0c;将匹配的行显示到标注输出。 语法 bzgrep(参数)参数 搜索模式&#xff1a;指定要搜索的模式&#xff1b;.bz2文件&#xff1a…

【教3妹学编程-算法题】K 个元素的最大和

3妹&#xff1a;“太阳当空照&#xff0c;花儿对我笑&#xff0c;小鸟说早早早&#xff0c;你为什么背上炸药包” 2哥 :3妹&#xff0c;什么事呀这么开发。 3妹&#xff1a;2哥你看今天的天气多好啊&#xff0c;阳光明媚、万里无云、秋高气爽&#xff0c;适合秋游。 2哥&#x…

【前端开发】JS Vue React中的通用递归函数

目录 前言 一、递归函数的由来 二、功能实现 1.后台数据 2.处理数据 3.整体代码 总结 &#x1f642;博主&#xff1a;冰海恋雨. &#x1f642;文章核心&#xff1a;【前端开发】JS Vue React中的通用递归函数 前言 大家好&#xff0c;今天和大家分享一下在前端开发中j…

基于springboot实现校园医疗保险管理系统【项目源码】

基于springboot实现校园医疗保险管理系统演示 系统开发平台 在线校园医疗保险系统中&#xff0c;Eclipse能给用户提供更多的方便&#xff0c;其特点一是方便学习&#xff0c;方便快捷&#xff1b;二是有非常大的信息储存量&#xff0c;主要功能是用在对数据库中查询和编程。其…

旺店通·企业版对接打通金蝶云星空查询调拨单接口与分布式调入单新增接口

旺店通企业版对接打通金蝶云星空查询调拨单接口与分布式调入单新增接口 源系统:旺店通企业版 旺店通是北京掌上先机网络科技有限公司旗下品牌&#xff0c;国内的零售云服务提供商&#xff0c;基于云计算SaaS服务模式&#xff0c;以体系化解决方案&#xff0c;助力零售企业数字化…

msys2 + MSVC(VS2019)编译ffmpeg6.0源码

以前使用的v1.2版&#xff0c;很多功能和使用方法发生了变化&#xff0c;需要重新编译新的ffmpeg版。 编译环境: windows 10 , VS2019, MSYS2 1. msys2 下载安装 MSYS2 , https://www.msys2.org/ 2. msys2 环境配置打开 msys2 2.1 安装相关软件 然后输入以下命令安装&…

gmpy2 GMP is_prime函数底层c代码分析

偶然看到一篇paper&#xff08;2018年发表&#xff09;&#xff0c;说GMP中的素性检测使用的是单独的Miller_Rabin方法&#xff0c;单独的Miller_Rabin素性检测会存在部分安全问题&#xff08;低概率&#xff09;&#xff0c;然后突然想求证一下最新版本的GMP中是否进行了修改。…

Python如何使用Matplotlib模块的pie()函数绘制饼形图?

Python如何使用Matplotlib模块的pie函数绘制饼形图&#xff1f; 1 模块安装2 实现思路3 pie()函数说明4 实现过程4.1 导入包4.2 定义一个类4.3 读取数据并处理4.4 定义饼图绘制方法 5 完整源码 1 模块安装 先安装matplotlib&#xff1a; pip install matplotlib安装numpy模块…

Linux Docker 图形化工具 Portainer远程访问

文章目录 前言1. 部署Portainer2. 本地访问Portainer3. Linux 安装cpolar4. 配置Portainer 公网访问地址5. 公网远程访问Portainer6. 固定Portainer公网地址 前言 Portainer 是一个轻量级的容器管理工具&#xff0c;可以通过 Web 界面对 Docker 容器进行管理和监控。它提供了可…

exsi的安装和配置

直接虚拟真实机 vcent server 管理大量的exsi SXI原生架构模式的虚拟化技术&#xff0c;是不需要宿主操作系统的&#xff0c;它自己本身就是操作系统。因此&#xff0c;装ESXI的时候就等同于装操作系统&#xff0c;直接拿iso映像(光盘)装ESXI就可以了。 VMware vCente…

在Vue.js中,什么是slot(插槽)?它的作用是什么?

聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…

2.6 Windows驱动开发:使用IO与DPC定时器

本章将继续探索驱动开发中的基础部分&#xff0c;定时器在内核中同样很常用&#xff0c;在内核中定时器可以使用两种&#xff0c;即IO定时器&#xff0c;以及DPC定时器&#xff0c;一般来说IO定时器是DDK中提供的一种&#xff0c;该定时器可以为间隔为N秒做定时&#xff0c;但如…

万宾科技内涝积水监测仪效果,预警城市积水

当城市之中出现强降雨或者大暴雨&#xff0c;可能会导致雨水不断堆积到城市排水管网之中&#xff0c;可能还会淹没城市的排水系统时&#xff0c;这种现象被称为城市之中的内涝&#xff0c;并且在许多城市之中内涝问题日益引起人们的关注。 内涝积水监测仪的出现成为了希望的灯塔…

4种互斥机制比较

4种互斥机制 关中断禁止任务切换信号量互斥信号量 关中断 关中断&#xff08;Disable Interrupts&#xff09;&#xff1a;通过禁用中断来实现互斥。在关中断期间&#xff0c;任何中断请求都会被忽略&#xff0c;从而确保了临界区的独占性。然而&#xff0c;这种方法会导致系统…