从仿写持久层框架到MyBatis核心源码阅读

news2025/1/25 1:38:20

接上篇手写持久层框架:https://blog.csdn.net/liwenyang1992/article/details/134884703

MyBatis源码

MyBatis架构原理&主要组件

MyBatis架构设计

在这里插入图片描述

MyBatis架构四层作用是什么呢?

API接口层:提供API,增加、删除、修改、查询等接口,通过API接口对数据库进行操作。

数据处理层:主要负责SQL的 查询、解析、执行以及结果映射的处理,主要作用解析SQL根据调用请求完成一次数据库操作。

框架支撑层:负责通用基础服务支撑,包含事务管理、连接池管理、缓存管理等共用组件的封装,为上层提供基础服务支撑。

在这里插入图片描述

包路径org.apache.ibatis

包路径作用备注
annotationsMapper映射器接口中使用到的注解
bindingMapper映射器接口与映射语句关系绑定构建
builderConfiguration配置的构建包
cache缓存实现与定义(包含一级/二级缓存)
cursor游标(针对查询结果集的获取与遍历等)
datasource数据源/连接池
exceptions异常包
executor语句执行器(包含参数/结果集/语句处理等)
io资源读取辅助包
jdbcMyBatis内部的SQL脚本运行的测试包
logging一套日志接口和适配器包
mappingMapper映射器相关参数/语句/结果/类型等对象包
parsingXML解析包(例如#{}占位符解析)
plugin插件包
reflection反射处理工具包
scriptingSQL执行脚本的解析处理包
session数据库连接会话核心包(会话创建/管理/调用)
transaction事务
type类型处理器(定义bean与数据库类型的转换关系)
XML映射器

MyBatis的真正强大在于它的语句映射,这是它的魔力所在,由于它的异常强大,映射器的XML文件就显得相对简单。如果拿它跟具有相同功能的JDBC代码进行对比,你会立即发现省掉了将近95% 的代码。MyBatis致力于减少使用成本,让用户能更专注于 SQL 代码。

SQL 映射文件只有很少的几个顶级元素(按照应被定义的顺序列出):

  • cache:该命名空间的缓存配置
  • cache-ref:引用其它命名空间的缓存配置。
  • resultMap:描述如何从数据库结果集中加载对象,是最复杂也是最强人的元素
  • sql:可被其它语句引用的可重用语句块。
  • insert:映射插入语句。
  • update:映射更新语句
  • delete:映射删除语句。
  • select:映射查询语句。
select

select元素允许你配置很多属性来配置每条语句的行为细节

    <select
            id="select"
            parameterType="int"
            resultType="resultType"
            resultMap="resultMap"
            flushCache="false"
            useCache="true"
            timeout="10"
            fetchSize="256"
            statementType="PREPARED"
            resultSetType="FORWARD_ONLY"></select>
insert, update 和 delete

数据变更语句insert, update 和 delete 的实现非常接近

动态SQL

借助功能强大的基于OGNL的表达式,MyBatis 3 替换了之前的大部分元素,大大精简了元素种类

<select id="findActiveBlogLike"
     resultType="Blog">
  SELECT * FROM BLOG WHERE state = ‘ACTIVE’
  <choose>
    <when test="title != null">
      AND title like #{title}
    </when>
    <when test="author != null and author.name != null">
      AND author_name like #{author.name}
    </when>
    <otherwise>
      AND featured = 1
    </otherwise>
  </choose>
</select>

XMLScriptBuilder

public SqlSource parseScriptNode()方法:

  1. 解析select、insert、update、delete标签中的SQL语句
  2. 最终将解析到的SqlNode封装到MixedSqlNode中的List集合中
  • 将带有${}号的SQL信息封装到TextSqlNode
  • 将带有#{}号的SQL信息封装到StaticTextSqlNode
  • 将动态SQL标签中的SQL信息分别封装到不同的SqlNode中
  • 如果SQL中包含${}和动态SQL语句,则将SqlNode封装到DynamicSqlSource

在这里插入图片描述

相关类与接口
DefaultSqlSession

SqlSession接口的默认实现类

Executor接口:

在这里插入图片描述

BaseExecutor:基础执行器,封装了子类的公共方法及公共变量,包括一级缓存、延迟加载、回滚、关闭等功能;

SimpleExecutor:简单执行器,每执行一条SQL,都会打开一个 Statement,执行完成后关闭;

ReuseExecutor:重用执行器,相较于 SimpleExecutor多了 Statement 的缓存功能,其内部维护一个Map<String, Statement>,每次编译完成的Statement 都会进行缓存,不会关闭;

BatchExecutor:批量执行器,基于JDBC的addBatch、executeBatch功能,并且在当前SQL和上一条SQL完全一样的时候,重用Statement,在调用doFlushStatements的时候,将数据刷新到数据库;

CachingExecutor:缓存执行器,装饰器模式,在开启缓存的时候。会在上面三种执行器的外面包上 CachingExecutor;

缓存执行过程

在这里插入图片描述

SimpleExecutor#doQuery

在这里插入图片描述

  • BaseStatementHandler:基础语句处理器(抽象类),它基本把语句处理器接口的核心部分都实现了,包括配置绑定、执行器绑定、映射器绑定、参数处理器构建、结果集处理器构建、语句超时设置、语句关闭等,并另外定义了新的方法 instantiateStatement供不同子类实现以使获取不同类型的语句连接,子类可以普通执行 SQL语句,也可以做预编译执行,还可以执行存储过程等
  • SimpleStatementHandler:普通语句处理器,继承BaseStatementHandler抽象类,对应 java.sql.Statement 对象的外理,处理普通的不带动态参数运行的SQL,即执行简单拼接的字符串语句,同时由于 Statement 的特性,SimpleStatementHandler 每次执行都需要编译 SQL**(注意:我们知道 SQL 的执行是需要编译和解析的)。**
  • PreparedStatementHandler:预编译语句处理器,继承BaseStatementHandler抽象类,对应 java.sql.PrepareStatement 对象的处理,相比上面的普通语句处理器,它支持可变参数 SQL执行,由于 PrepareStatement 的特性,它会进行预编译,在缓存中一旦发现有预编译的命令,会直接解析执行,所以减少了再次编译环节,能够有效提高系统性能,并预防 SQL 注入攻击**(所以是系统默认也是我们推荐的语句处理器)**
  • CallableStatementHandler:存储过程外理器,继承BaseStatementHandler抽象类,对应 java.sql.CallableStatement 对象的处理,很明了,它是用来调用存储过程的,增加了存储过程的函数调用以及输出/输入参数的处理支持。
  • RoutingStatementHandler:路由语句处理器,直接实现了 StatementHandler 接口,作用如其名称,确确实实只是起到了路由功能,并把上面介绍到的三个语句处理器实例作为自身的委托对象而已,所以执行器在构建语句处理器时,都是直接 new了RoutingStatementHandler实例。

附件中包含测试用例代码,可设置jdk17调试运行,带注解。

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

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

相关文章

20231228在Firefly的AIO-3399J开发板的Android11的挖掘机的DTS配置单前置摄像头ov13850

20231228在Firefly的AIO-3399J开发板的Android11的挖掘机的DTS配置单前置摄像头ov13850 2023/12/28 10:42 【碰到一个很神奇的问题】&#xff1a; 昨天晚上前置摄像头怎么也点不亮&#xff01;改了巨多的地方&#xff01;晚上睡觉之前把开发板彻底断电了&#xff01;今天开电脑…

SLAM学习入门--机器学习

文章目录 机器学习逻辑回归&#xff08;LR&#xff09;基本原理为什么 LR 要使用 sigmoid 函数&#xff1f;LR 可以用核函数么&#xff1f;为什么 LR 用交叉熵损失而不是平方损失&#xff1f;LR 能否解决非线性分类问题&#xff1f;LR为什么要离散特征&#xff1f;逻辑回归是处…

51和32单片机读取FSR薄膜压力传感器压力变化

文章目录 简介线性电压转换模块51单片机读取DO接线方式51代码实验效果 32单片机读取AO接线方式32代码实验效果 总结 简介 FSR薄膜压力传感器是可以将压力变化转换为电阻变化的一种传感器&#xff0c;单片机可以读取然后作为粗略测量压力&#xff08;仅提供压力变化&#xff0c;…

各部门请注意,VELO维乐潮流骑士尼莫出街啦,快来加入吧!

VELO潮流骑士丨车界“小学生”尼莫&#xff0c;下面是来自她的自诉&#xff1a;      大家好&#xff01;我是尼莫&#xff0c;一枚骑车届的“小学生”&#xff0c;我爱上骑车已经有一年的时间啦&#xff01;在这一年的时间里&#xff0c;骑车改变了我很多&#xff1a;爱上…

java虚拟机内存管理

文章目录 概要一、jdk7与jdk8内存结构的差异二、程序计数器三、虚拟机栈3.1 什么是虚拟机栈3.2 什么是栈帧3.3 栈帧的组成 四、本地方法栈五、堆5.1 堆的特点5.2 堆的结构5.3 堆的参数配置 六、方法区6.1 方法区结构6.2 运行时常量池 七、元空间 概要 根据 JVM 规范&#xff0…

关于HTTPS

目录 什么是加密 对称加密 非对称加密 中间人攻击 引入证书 HTTPS是一个应用层的协议,是在HTTP协议的基础上引入了一个加密层. HTTP协议内容都是按照文本的方式明文传输,这就导致在传输的过程中出现一些被篡改的情况. 运营商劫持事件 未被劫持的效果,点击下载按钮,就会…

52.网游逆向分析与插件开发-游戏反调试功能的实现-检测调试器

码云地址&#xff08;master分支&#xff09;&#xff1a;https://gitee.com/dye_your_fingers/sro_-ex.git 码云版本号&#xff1a;be9f058bfaaa4b015f2659db842e07ee37e58996 代码下载地址&#xff0c;在 SRO_EX 目录下&#xff0c;文件名为&#xff1a;SRO_Ex检测调试器.z…

构建基于小红书笔记详情API的内容生态

随着互联网的发展&#xff0c;内容生态的构建已经成为了许多企业和个人的重要任务。小红书作为一家以内容分享为主的社交平台&#xff0c;其API的开放为开发者提供了一种全新的方式来获取用户生成内容&#xff08;UGC&#xff09;。本文将介绍如何从无到有地构建基于小红书笔记…

Analytify Pro Google Analytics Goals Addon谷歌分析目标插件

Analytify Pro Google Analytics Goals Addon谷歌分析目标插件是一款极其巧妙且具有开创性的工具&#xff0c;它赋予用户细致跟踪和全面分析其网站性能的卓越能力。有了这个非凡的插件&#xff0c;个人可以毫不费力地建立并认真监控他们的Google Analytics目标&#xff0c;从而…

【docker实战】01 Linux上docker的安装

Docker CE是免费的Docker产品的新名称&#xff0c;Docker CE包含了完整的Docker平台&#xff0c;非常适合开发人员和运维团队构建容器APP。 Ubuntu 14.04/16.04&#xff08;使用 apt-get 进行安装&#xff09; # step 1: 安装必要的一些系统工具 sudo apt-get update sudo ap…

vscode调试 反汇编c/c++ 查看汇编代码gdb/lldb

先看下流程&#xff01; 先看下流程&#xff01; 有问题请留言&#xff01; 文章目录 必备F5开启调试左侧侧边栏->确保打开回调栈右键函数栈->查看反汇编 方法二&#xff1a;手动输入命令查看 必备 使用c/c 插件&#xff0c;这应该是必备的。 F5开启调试 左侧侧边栏-&…

Vue学习计划-Vue3--初识Vue3,vite创建Vue3项目

1. Vue3简介 性能的提升 打包大小减少41%初次渲染快55%&#xff0c;更新渲染快133%内存减少54% 源码的升级 使用Proxy代替defineProperty实现响应式重写虚拟DOM的实现和Tree-Shaking 拥抱TypeScript Vue3可以更好的支持TypeScript 新的特性 Composition Api(组合Api) setupref…

20231228在Firefly的AIO-3399J开发板的Android11使用Firefly的DTS配置单前后摄像头ov13850

20231228在Firefly的AIO-3399J开发板的Android11使用Firefly的DTS配置单前后摄像头ov13850 2023/12/28 19:20 缘起&#xff0c;突然发现只能打开前置的ov13850&#xff0c;或者后置的ov13850。 但是不能切换&#xff01; 【SDK&#xff1a;rk3399-android-11-r20211216.tar.xz】…

EasyExcel详解(结合官方文档)

EasyExcel 零、前言 文章是根据官方文档&#xff0c;加上自己的测试运行总结出来的&#xff0c;目前只总结的EasyExcel读的部分&#xff0c;写的部分还未完结&#xff0c;后续会更新1、官方文档 https://easyexcel.opensource.alibaba.com/2、EasyExcel的maven依赖 <!--…

【SpringBoot】常用注解

RequestBody&#xff1a;自动将请求体中的 json 数据转换为实体类对象。 PutMapping("/update")public Result update(RequestBody Validated User user) {userService.update(user);return Result.success();}

OPenGL GLSL

shji 数据类型 整型&#xff08;有符号/无符号&#xff09; 浮点数&#xff08;单精度&#xff09; 布尔值 向量类型/矩阵类型 bool bDone false int value 1; unint vale 21u float value 2.1 向量/分量类型 vec2,vec3,vec4 2分量 3 分量 4 分量复电向量 i…

CDH 6.3.2集成flink 1.18 zookeeper版本不匹配Flink-yarn启动失败

CDH 6.3.2集成flink 1.18 zookeeper版本不匹配Flink-yarn不能正常启动&#xff0c;而在CHD Web页面&#xff0c;flink日志报错提示不明确&#xff0c;不能定位具体错误。CM WEB启动失败错误日志如下图所示&#xff1a; CM查看完成错误日志 [31/Dec/2023 10:45:09 0000] 26000…

同义词替换降低论文相似度的注意事项 papergpt

大家好&#xff0c;今天来聊聊同义词替换降低论文相似度的注意事项&#xff0c;希望能给大家提供一点参考。 以下是针对论文重复率高的情况&#xff0c;提供一些修改建议和技巧&#xff0c;可以借助此类工具&#xff1a; 标题&#xff1a;同义词替换降低论文相似度的注意事项 …

git分支场景操作,应用场景

文章目录 git分支操作1.git branch--目前处在的分支上2.git checkout--要切换的分支名字3.git merge--要合并的分支名字4.git branch -d--要删除的分支名字 git分支操作 假设目前我们目前有三个版本 1.git branch–目前处在的分支上 现在要开发一个新功能在新的分支上 新建一…

\r\n和缓冲区/进度条小程序

一 前置知识 带有\n就会立马刷新缓冲区(因为显示器是行刷新)&#xff0c;\r不会刷新缓冲区 刷新的2个场景: 1 ~fflush 缓冲区中存在\r或\n --> \r fflush --> 不换行的\n) 2 ~ 文件关闭自动刷新缓冲区 倒计时小程序0-9 %-d是左对齐,%d是右对齐 倒计时小程序0-99 …