MyBatis架构原理详解

article/2025/9/1 12:51:57

1. Mybatis架构设计

MyBatis 是 Java 生态中非常著名的一款 ORM 框架,目前在一线互联网大厂中应用广泛,Mybatis已经成为了一个必会框架。

Mybatis的功能架构分为三层:

  1. API接口层
  2. 数据处理层
  3. 基础支撑层

2. API接口层

接口层:主要就是和数据库交互,提供给外部使用的接口API,开发人员通过这些本地API来操纵数据库,接口层一接收到调用请求就会调用数据处理层来完成具体的数据处理。

以使用Mapper接口为例,将Mapper文件抽象为一个Mapper接口,这个接口中声明的方法和跟Mapper.xml中的节点项对应。

id值对应方法名称,parameterType 值对应方法的入参类型,而resultMap 值则对应返回值类型。

配置好后,MyBatis 会根据接口声明的方法信息,通过动态代理机制生成一个Mapper 实例,当调用接口方法时,根据这个方法的方法名和参数类型,确定Statement Id,底层还是通过 SqlSession.select/update( “statementId”, parameter) 等来实现对数据库的操作。

3. 数据处理层

数据处理层:可以说是MyBatis 的核心,负责具体的SQL查找、SQL解析、SQL执行和执行结果映射处理等,它主要的目的是根据调用的请求完成一次数据库操作。

从大的方面上讲,它要完成两个功能:1. 通过传入参数构建动态SQL语句;2. SQL语句的执行以及封装查询结果集。

3.1 通过传入参数构建动态SQL语句

动态语句生成能够说是MyBatis框架很是优雅的一个设计,MyBatis 经过传入的参数值,使用 Ognl 来动态地构造SQL语句,使得MyBatis 有很强的灵活性和扩展性。

参数映射指的是对于java 数据类型和jdbc数据类型之间的转换,这里有包括两个过程:

  • 查询阶段
  • 查询结果集转换阶段

查询阶段要将java类型的数据,转换成jdbc类型的数据,经过 preparedStatement.setXXX() 来设值;

另外一个就是对resultset查询结果集的jdbcType 数据转换成java 数据类型。

3.2 SQL语句的执行以及封装查询结果集

动态SQL语句生成以后,MyBatis 将执行SQL语句,并将可能返回的结果集转换成List<E> 列表。

MyBatis 在对结果集的处理中,支持结果集关系一对多和多对一的转换,而且有两种支持方式,一种为嵌套查询语句的查询,还有一种是嵌套结果集的查询。

4. 基础支撑层

基础支撑层是整个MyBatis框架的地基,负责最基础的功能支撑,包括连接管理、事务管理、配置加载和缓存处理,这些都是共用的东西,将他们抽取出来作为最基础的组件,为上层的数据处理层提供最基础的支撑。

4.1 缓存机制

数据库是实践生产中非常核心的存储,很多业务数据都会落地到数据库,所以数据库性能的优劣直接影响了上层业务系统的优劣。

我们很多线上业务都是读多写少的场景,在数据库遇到瓶颈时,缓存是最有效、最常用的手段之一,正确使用缓存可以将一部分数据库请求拦截在缓存这一层,这就能够减少一部分数据库的压力,提高系统性能。

除了使用 Redis、Memcached 等外置的第三方缓存以外,持久化框架一般也会自带内置的缓存,例如,MyBatis 就提供了一级缓存和二级缓存,具体实现位于基础支撑层的缓存模块中。

4.1.1 一级缓存与二级缓存

一级缓存:SqlSession级别的缓存,缓存的数据只在SqlSession内有效。(范围小)

二级缓存:mapper级别的缓存,同一个namespace公用这一个缓存,所以对SqlSession是共享的,二级缓存需要我们手动开启。(范围大)

4.1.2 一级缓存

当我们使用Mybatis进行数据库的操作时候,会创建一个SqlSession来进行一次数据库的会话,会话结束则关闭SqlSession对象。

如果我们很有可能多次查询完全相同的sql语句,每一次查询都查询一次数据库,那查询数据库代价是比较大的,这会导致系统的资源浪费。

为了解决这个问题,Mybatis对每一次会话都添加了缓存操作,不用相同的SQL每次都需要查询数据库,这就是Mybatis一级缓存的作用。

Mybatis一级缓存的实现

我们知道对SqlSession的操作,mybatis内部都是通过Executor来执行的,Executor的生命周期和SqlSession是一致的。

Mybatis在Executor中创建了本地缓存(一级缓存),如下图所示:

大致的流程如下:

1. 第一次查询用户id信息,先去缓存中查询是否有,如果没有,从数据库中查询用户信息,得到用户信息后在将用户信息储存到一级缓存中。

2. 如果sqlSession去执行commit操作(插入、更新、删除),清空sqlSession中的一级缓存,保证缓存中始终保存的是最新的信息,避免脏读。

3. 第二次查询用户id信息,先去缓存中查询,如缓存中有,直接从缓存中获取。

注意:两次查询须在同一个sqlsession中完成,否则将不会走mybatis的一级缓存。在mybatis与spring进行整合开发时,事务控制在service中进行,重复调用两次servcie将不会走一级缓存,因为在第二次调用时session方法结束,SqlSession就关闭了。

Mybatis一级缓存配置

mybatis一级缓存的范围有SESSION和STATEMENT两种,默认是SESSION。

如果不想使用一级缓存,可以把一级缓存的范围指定为STATEMENT,这样每次执行完一个Mapper中的语句后都会将一级缓存清除。

如果需要更改一级缓存的范围,可以在Mybatis的配置文件中,在下通过localCacheScope指定。

<setting name="localCacheScope" value="STATEMENT"/>

4.1.3 二级缓存

MyBatis 一级缓存最大的共享范围就是一个SqlSession内部,那么如果多个 SqlSession 需要共享缓存,则需要开启二级缓存。

Mybatis二级缓存的实现

开启二级缓存后,会使用 CachingExecutor 装饰 Executor,进入一级缓存的查询流程前,先在 CachingExecutor 进行二级缓存的查询,具体的工作流程如下所示。

二级缓存开启后,同一个 namespace 下的所有操作语句,都影响着同一个 Cache,即二级缓存被多个 SqlSession 共享,是一个全局的变量。

当开启缓存后,数据的查询执行的流程就是 二级缓存 -> 一级缓存 -> 数据库。

MyBatis 是默认关闭二级缓存的,因为对于增删改操作频繁的话,那么二级缓存形同虚设,每次都会被清空缓存。

Mybatis二级缓存配置

方式一:在xml文件中配置<!--开启二级缓存-->
<setting name="cacheEnabled" value="true"/>方式二:在mapper接口上添加上
@CacheNamespace后面可以带参数指定加载自定义的缓存实现类(自定义的缓存,或者Redis缓存)
@CacheNamespace(implementation = RedisCache.class)// 开启二级缓存

4.1.4 Mybatis一级缓存与二级缓存的区别

1)一级缓存 Mybatis的一级缓存是指SQLSession,一级缓存的作用域是SQlSession, Myabits默认开启一级缓存。

在同一个SqlSession中,执行相同的SQL查询时;第一次会去查询数据库,并写在缓存中,第二次会直接从缓存中取。 当执行SQL时候两次查询中间发生了增删改的操作,则SQLSession的缓存会被清空。

每次查询会先去缓存中找,如果找不到,再去数据库查询,然后把结果写到缓存中。 Mybatis的内部缓存使用一个HashMap,key为hashcode+statementId+sql语句。Value为查询出来的结果集映射成的java对象。 SqlSession执行insert、update、delete等操作commit后会清空该SQLSession缓存。

2) Mybatis二级缓存是默认不开启的,作用于一个Application,是Mapper级别的,多个SqlSession使用同一个Mapper的sql能够使用二级缓存。

4.2 反射工具

该模块对 Java 原生的反射进行了良好的封装,提供了更加简洁易用的 API ,方便上层使调用,并且对反射操作进行了一系列优化,例如缓存了类的元数据,提高了反射操作的性能。

4.3 类型转换

类型转换模块提供了两个主要功能,一个功能是别名机制,MyBatis 为了简化配置文件提供了别名机制

另一个功能是实现 JDBC 类型与 Java 类型之间的转换,该功能在为 SQL 语句绑定实参以及映射查询结果集时都会涉及。

4.4 日志

提供详细的日志输出信息,并且能够集成多种日志框架,其日志模块的一个主要功能就是集成第三方日志框架

4.5 资源加载

资源加载模块主要是对类加载器进行封装,确定类加载器的使用顺序,并提供了加载类文件以及其他资源文件的功能。

4.6 解析器

解析器模块主要提供两个功能,一个功能是对 XPath 进行封装,为 MyBatis 初始化时解析 mybatis-config.xml 配置文件以及映射配置文件提供支持。

另一个功能是为处理动态 SQL 语句中的占位符提供支持。

4.7 事务管理

持久层框架一般都会提供一套事务管理机制实现数据库的事务控制,MyBatis 对数据库中的事务进行了一层简单的抽象,提供了简单易用的事务接口和实现。

一般情况下,Java 项目都会集成 Spring,并由 Spring 框架管理事务。

4.8 Binding

在调用 SqlSession 相应方法执行数据库操作时,需要指定映射文件中定义的 SQL 节点,如果出现拼写错误,我们只能在运行时才能发现相应的异常。为了尽早发现这种错误,MyBatis 通过 Binding 模块将用户自定义的 Mapper 接口与映射配置文件关联起来,系统可以通过调用自定义 Mapper 接口中的方法执行相应的SQL 语句完成数据库操作,从而避免上述问题。

需要注意的是,开发人员无须编写自定义 Mapper 接口的实现,MyBatis 会自动为其创建动态代理对象。

5. 数据源

对于 ORM 框架而言,数据源的组织是一个非常重要的一部分,这直接影响到框架的性能问题。

数据库连接是一项有限的昂贵资源,一个数据库连接对象均对应一个物理数据库连接,每次操作都打开一个物理连接,使用完都关闭连接,这样造成系统的性能低下。

数据库连接池的解决方案是在应用程序启动时建立足够的数据库连接,并将这些连接组成一个连接池,由应用程序动态地对池中的连接进行申请、使用和释放。

打开Mybatis源码找到datasource包下就可以看到连接池的实现,如下图所示:

6. Mybatis核心执行流程 

6.1 MyBatis配置文件

config.xml:配置了全局配置文件,配置了MyBatis的运行环境等信息。

mapper,xml:sql的映射文件,配置了操作数据库的sql语句,此文件需在config.xml中加载。

6.2 SqlSessionFactory

通过MyBatis环境等配置信息构造SqlSessionFactory(会话工厂)。

6.3 SqlSession

通过会话工厂创建SqlSession(会话),对数据库进行增删改查操作。

6.4 Exector执行器

MyBatis底层自定义了Exector执行器接口来具体操作数据库,Exector接口有两个实现,一个基本执行器(默认),一个是缓存执行器,SqlSession底层是通过Exector接口操作数据库。

6.5 MappedStatement

MyBatis的一个底层封装对象,它包装了MyBatis配置信息与sql映射信息等。mapper.xml中的insert/select/update/delete标签对应一个MappedStatement对象。标签的id就是MappedStatement的id。

MappedStatement对sql执行输入参数进行定义,包括HashMap、基本类型、pojo、Executor通过MappedStatement在执行sql前将输入的Java对象映射至sql中,输入参数映射就是JDBC编程对preparedStatement设置参数。

MappedStatement对sql执行输出结果进行定义,包括HashMap、基本类型、pojo,Executor通过MappedStatement在执行sql后将输出结果映射至Java对象中,输出结果映射就是JDBC编程对结果的解析处理过程。

参考:深入详解Mybatis的架构原理与6大核心流程 - mikechen的互联网架构 - 博客园 (cnblogs.com)


http://chatgpt.dhexx.cn/article/6MNhfebq.shtml

相关文章

springboot集成mybatis原理剖析

前言&#xff1a;本文主要基于springboot项目&#xff0c;从springboot的拓展角度来分析mybatis是如何与springboot集成的。 1、首先搭建springboot集成mybatis环境 1.1、maven pom文件依赖 <?xml version"1.0" encoding"UTF-8"?> <project x…

MyBatis原理分析(通俗易懂)

MyBatis原理分析 MyBatis工作流程简述原生MyBatis原理分析初始化工作解析配置文件配置类方式 执行SQLSqlSession API方式接口方式 真正掌握一个框架源码分析是少不了的~ 在讲解整合Spring的原理之前理解原生的MyBatis执行原理是非常有必要的 MyBatis工作流程简述 传统工作模…

【MyBatis学习笔记九】——MyBatis原理

一、Mybatis工作原理图 mybatis 原理图如下所示&#xff1a; 二、工作原理解析 mybatis应用程序通过SqlSessionFactoryBuilder从mybatis-config.xml配置文件&#xff08;也可以用Java文件配置的方式&#xff0c;需要添加Configuration&#xff09;来构建SqlSessionFactory&…

【mybatis原理工作原理】

文章目录 mybatis原理&#xff1a;mybatis缓存机制 mybatis原理&#xff1a; mybatis的工作原理就是&#xff1a;先封装sql&#xff0c;接着调用jdbc操作数据库&#xff0c;最后把数据库返回的表结果封装成java类。 通过代码实现jdbc查询操作&#xff1a; mybatis-config.xm…

mybatis原理(含图)

上面中流程就是MyBatis内部核心流程&#xff0c;每一步流程的详细说明如下文所述&#xff1a; &#xff08;1&#xff09;读取MyBatis的配置文件。mybatis-config.xml为MyBatis的全局配置文件&#xff0c;用于配置数据库连接信息。 &#xff08;2&#xff09;加载映射文件。映…

MyBatis原理分析

是什么? MyBatis 是一款优秀的持久层框架&#xff0c;它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis可以使用简单的 XML 或注解来配置和映射原生类型、接口和 Java 的 POJO&#xff08;Plain Old Java …

Spring 整合 Mybatis 原理

目录 Mybatis的基本工作原理分析需要解决的问题Spring中Bean的产生过程解决问题解决方案FactoryBean Import总结优化 Mybatis的基本工作原理 在 Mybatis 中&#xff0c;我们可以使用一个接口去定义要执行 sql&#xff0c;简化代码如下&#xff1a;定义一个接口&#xff0c;Sel…

Springboot整合mybatis原理

文章目录 加载过程1、读取META-INF/spring.factories配置文件里需要自动装载的类2、解析MybatisAutoConfiguration类里的注解信息&#xff0c;将需要管理的Bean注册到Spring容器2.1 注册SqlSessionFactory&#xff0c;并根据mapper配置文件解析出dao与具体jdbc操作、resultMap与…

【mybatis原理】

mybatis mybatis原理mybatis框架分层架构核心接口和对象mapper接口与xml的映射mybatis执行过程mybatis执行时序图一级缓存和二级缓存一级缓存二级缓存 mybatis核心流程1、初始化阶段2、代理阶段3、数据读写阶段 mybatis如何获取数据源mybatis如何获取执行SQLMyBatis 如何执行 s…

Mybatis原理

文章目录 - 什么是Mybatis&#xff1f;- Mybaits的优点&#xff1a;- MyBatis框架的缺点&#xff1a;- MyBatis与Hibernate有哪些不同&#xff1f;- 架构MyBatis缓存一级缓存一级缓存和sqlsession之间的关系一级缓存的生命周期有多长&#xff1f;SqlSession 一级缓存的工作流程…

深入详解Mybatis的架构原理与6大核心流程

MyBatis 是 Java 生态中非常著名的一款 ORM 框架&#xff0c;目前在一线互联网大厂中应用广泛&#xff0c;Mybatis已经成为了一个必会框架。 如果你想要进入一线大厂&#xff0c;能够熟练使用 MyBatis 开发已经是一项非常基本的技能&#xff0c;同时大厂也更希望自己的开发人员…

总结Mybatis的原理

一、什么是Mybatis Mybatis是一个半ORM&#xff08;对象关系映射&#xff09;框架&#xff0c;底层封装了JDBC&#xff0c;是程序员在开发时只需要关注SQL语句本身&#xff0c;不需要花费精力去处理加载驱动、创建连接、创建statement等繁杂的过程。MyBatis 可以使用简单的 XM…

MyBatis基本工作原理介绍

1、MyBatis基本工作原理介绍 计算机的基本工作就是存储和计算&#xff0c;而MyBatis是存储领域的利器。MyBatis的基本工作原理就是&#xff1a;先封装SQL&#xff0c;接着调用JDBC操作数据库&#xff0c;最后把数据库返回的表结果封装成Java类。 2、MyBatis的核心流程介绍 m…

Mybatis 工作原理详解

目录 Mybatis持久层框架 结果集进行ORM映射 步骤解析 1、获取结果集及结果映射入口 2、开始ORM映射接口 3、数据库结果集解析&#xff0c;完成ORM映射 4、保存并获取ORM映射后的结果集 参数传递方式 顺序传参法 Param注解传参法 Map传参法 Java Bean传参法 mybat…

《深入理解mybatis原理》 MyBatis的架构设计以及实例分析

MyBatis是目前非常流行的ORM框架&#xff0c;它的功能很强大&#xff0c;然而其实现却比较简单、优雅。本文主要讲述MyBatis的架构设计思路&#xff0c;并且讨论MyBatis的几个核心部件&#xff0c;然后结合一个select查询实例&#xff0c;深入代码&#xff0c;来探究MyBatis的实…

【图片压缩】三个方法压缩图片体积

图片体积过大&#xff0c;会占用电脑过多的容量&#xff0c;也有可能无法发送给其他人。我们可以压缩图片体积来解决问题。分享三个方法压缩图片体积&#xff1a; 方法一&#xff1a;改变图片格式 首先是改变图片的格式&#xff0c;如果你不介意压缩之后的图片画质损失&#…

Windows不同压缩软件、压缩算法、压缩率详细对比测试与选择

上次写了图片压缩&#xff0c;这倒让我想起几年前看过的一个很有意思的东西 那就是这张鸭子图&#xff1a; 不过微信会压缩图片&#xff0c;你可以打开这个链接&#xff1a;http://2.im.guokr.com/F70Kn-4wz7aF5Yejf9W3g6kO4exDBqVEb0TumQmxy5MiAQAAEAEAAEpQ.jpg 来获取原图 …

为什么压缩图片和压缩

为什么要压缩图片&#xff1f; 表示图像需要大量的数据&#xff0c;但图像数据是高度相关的&#xff0c;或者说存在冗余(Redundancy)信息&#xff0c;去掉这些冗余信息后可以有效压缩图像&#xff0c;同时又不会损害图像的有效信息。 视网膜上有两种感光细胞&#xff0c;能够…

2款免费的图片压缩工具

今天写这篇文章的目的&#xff0c;主要是为大家介绍2款免费的图片压缩工具&#xff0c;在工作和学习中这也是一项必备的技能。比如当你遇到比较大的图片需要发送的时候&#xff0c;或者对图片的大小有强制要求的时候&#xff0c;这些小工具就派上了用场。 网上也有一些付费的压…

如何批量压缩图片体积大小kb?

工作中&#xff0c;我们在使用图片素材时&#xff0c;图片kb体积过大怎么办&#xff1f; 通常我们会直接在电脑上将图片调整成我们想要的尺寸大小&#xff0c;可以利用的工具有photoshop或者截图的方法&#xff0c;这对于有些小伙伴来说不是很难的事情&#xff0c;今天我就不做…