自己实现MyBatis 底层机制--抽丝剥茧(上)

😀前言
本篇博文是学习过程中的笔记和对于MyBatis底层机制的分析思路,希望能够给您带来帮助😊

🏠个人主页:晨犀主页
🧑个人简介:大家好,我是晨犀,希望我的文章可以帮助到大家,您的满意是我的动力😉😉

💕欢迎大家:这里是CSDN,我总结知识的地方,欢迎来到我的博客,感谢大家的观看🥰
如果文章有什么需要改进的地方还请大佬不吝赐教 先在次感谢啦😊

文章目录

  • 自己实现MyBatis 底层机制[上]
    • MyBatis 整体架构分析
      • Mybatis 核心框架示意图
      • 核心框架示意图的解读
    • 搭建MyBatis 底层机制开发环境
      • 1、创建Maven 项目nlc-mybatis
      • 2、修改nlc-mybatis\pom.xml
      • 3、创建数据库和表
      • 4、到此: 项目开发环境搭建完成
    • Nlc-Mybatis 的设计思路
      • Mybatis 的底层实现设计
        • 1. 传统方式操作数据库
        • 2.MyBatis操作数据库的方式分析
    • 自己实现MyBatis 底层机制
      • 实现任务阶段1- 完成读取配置文件,得到数据库连接
        • 分析示意图
        • 代码实现
        • 完成测试
        • 测试效果
    • 实现任务阶段2- 编写执行器,输入SQL 语句,完成操作
      • 分析示意图
      • 代码实现
      • 完成测试
    • 😄总结

自己实现MyBatis 底层机制[上]

MyBatis 整体架构分析

Mybatis 核心框架示意图

核心框架示意图的解读

  1. mybatis 的核心配置文件
    mybatis-config.xml: 进行全局配置,全局只能有一个这样的配置文件
    XxxMapper.xml 配置多个SQL,可以有多个XxxMappe.xml 配置文件
  2. 通过mybatis-config.xml 配置文件得到SqlSessionFactory
  3. 通过SqlSessionFactory 得到SqlSession,用SqlSession 就可以操作数据了
  4. SqlSession 底层是Executor(执行器), 有两个重要的实现类基本执行器和带缓存功能的执行器, 有很多方法

  1. MappedStatement 是通过XxxMapper.xml 中定义, 生成的statement 对象
  2. 参数输入执行并输出结果集, 无需手动判断参数类型和参数下标位置, 且自动将结果集映射为Java 对象

搭建MyBatis 底层机制开发环境

1、创建Maven 项目nlc-mybatis

前面快速入门有创建步骤,这里不在描述。

2、修改nlc-mybatis\pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.nlc</groupId><artifactId>nlc-mybatis</artifactId><version>1.0-SNAPSHOT</version><!--定义编译器 / source / target 版本即可--><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target><java.version>1.8</java.version></properties><!--引入必要的依赖--><dependencies><!--引入dom4j--><dependency><groupId>dom4j</groupId><artifactId>dom4j</artifactId><version>1.6.1</version></dependency><!--引入mysql依赖--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.49</version></dependency><!--lombok-简化entity/javabean/pojo开发 --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.4</version></dependency><!--junit依赖--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version></dependency></dependencies>
</project>

3、创建数据库和表

CREATE DATABASE `nlc_mybatis`;
USE `nlc_mybatis`;
CREATE TABLE `monster` (`id` INT NOT NULL AUTO_INCREMENT,`age` INT NOT NULL,`birthday` DATE DEFAULT NULL,`email` VARCHAR(255) NOT NULL,`gender` TINYINT NOT NULL,`name` VARCHAR(255) NOT NULL,`salary` DOUBLE NOT NULL,PRIMARY KEY (`id`)
) CHARSET=utf8
INSERT INTO `monster` VALUES(NULL, 200, '2000-11-11', 'nmw@sohu.com', 1,'牛魔王', 8888.88)

4、到此: 项目开发环境搭建完成

Nlc-Mybatis 的设计思路

Mybatis 的底层实现设计

1. 传统方式操作数据库

  1. 得到Session对象

  2. 调用Executor的方法完成操作

  3. Executor的连接是从Configuration获取的

2.MyBatis操作数据库的方式分析

  1. 得到Session
  2. 不用直接调用Executor的方法完成操作
  3. 通过MapperProxy获取Mapper对象
  4. 调用Mapper的方法,完成数据库的操作
  5. Mapper最终还是动态代理方式,使用Executor的方法完成操作
  6. MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。

自己实现MyBatis 底层机制

实现任务阶段1- 完成读取配置文件,得到数据库连接

通过配置文件,获取数据库连接。

分析示意图

代码实现

  1. 创建nlc-mybatis\src\main\resources\nlc_config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<database><!--配置连接数据库的信息--><property name="driverClassName" value="com.mysql.jdbc.Driver"/><!--配置连接mysql-url1. jdbc:mysql 协议2. 127.0.0.1:3306 : 指定连接mysql的ip+port3. mybatis: 连接的DB4. useSSL=true 表示使用安全连接5. &amp; 表示 & 防止解析错误6. useUnicode=true : 使用unicode 作用是防止编码错误7. characterEncoding=UTF-8 指定使用utf-8, 防止中文乱码8. 不要背,直接使用即可--><property name="url" value="jdbc:mysql://localhost:3306/nlc_mybatis?useSSL=true&amp;useUnicode=true&amp;characterEncoding=UTF-8"/><property name="username" value="root"/><property name="password" value="123456"/>
</database>
  1. 创建nlc-mybatis\sqlsession\NlcConfiguration.java
public class NlcConfiguration {//属性-类的加载器private static ClassLoader loader =ClassLoader.getSystemClassLoader();//读取xml文件信息,并处理public Connection build(String resource) {Connection connection = null;try {//加载配置nlc_mybatis.xml 获取到对应的InputStreamInputStream stream =  loader.getResourceAsStream(resource);SAXReader reader = new SAXReader();Document document = reader.read(stream);//获取到nlc_mybatis.xml 的根元素 <database>Element root = document.getRootElement();System.out.println("root=" + root);//解析root元素,返回Connection connection = evalDataSource(root);} catch (Exception e) {e.printStackTrace();}return connection;}//方法会解析nlc_config.xml 信息,并返回Connection//eval: 评估/解析private Connection evalDataSource(Element node) {if (!"database".equals(node.getName())) {throw new RuntimeException("root 节点应该是<database>");}//连接DB的必要参数String driverClassName = null;String url = null;String username = null;String password = null;//遍历node下的子节点,获取属性值for (Object item : node.elements("property")) {Element i = (Element) item;//i 就是 对应property节点String name = i.attributeValue("name");String value = i.attributeValue("value");//判断是否得到name 和 valueif (name == null || value == null) {throw new RuntimeException("property 节点没有设置name或者value属性");}switch (name) {case "url":url = value;break;case "username":username = value;break;case "driverClassName":driverClassName = value;break;case "password":password = value;break;default:throw new RuntimeException("属性名没有匹配到...");}}Connection connection = null;try {//要求JVM查找并加载指定的类到内存中,此时将"com.mysql.jdbc.Driver" 当做参数传入,// 就是告诉JVM,去"com.mysql.jdbc"这个路径下找Driver类,将其加载到内存中。Class.forName(driverClassName);connection = DriverManager.getConnection(url,username,password);} catch (Exception e) {e.printStackTrace();}return connection; //返回Connection}}

完成测试

  1. 编写nlc-mybatis\src\test\java\com\nlc\test\NlcMybatisTest.java
public class NlcMyBatisTest {@Testpublic void build() {NlcConfiguration nlcConfiguration = new NlcConfiguration();Connection connection = nlcConfiguration.build("nlc_mybatis.xml");System.out.println("connection--" + connection);}
}

测试效果

实现任务阶段2- 编写执行器,输入SQL 语句,完成操作

说明:通过实现执行器机制,对数据表操作。

分析示意图

说明:我们把对数据库的操作,会封装到一套Executor 机制中,程序具有更好的扩展性,结构更加清晰.

代码实现

  1. 创建nlc-mybatis\src\main\java\com\nlc\entity\Monster.java

如果使用@Data注解需要全参构造器可以添加@AllArgsConstructor,但是无参构造器必须要显示调用,否则会被全参构造器覆盖。

/*** Monster 和 monster表有映射关系* @Getter 就会给所有属性 生成对应的getter* @Setter 就会给所有属性 生成对应的setter* @ToString 生成 toString...* @NoArgsConstructor 生成无参构造器* @AllArgsConstructor 生成要给全参构造器* @Data 会生成上面除全参构造器的所有注解* 如何选择主要还是看自己需要*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Monster {private Integer id;private Integer age;private String name;private String email;private Date birthday;private double salary;private Integer gender;}
  1. 创建nlc-mybatis\src\main\java\com\nlc\nlcmybatis\sqlsession\Executor.java
public interface Executor {//泛型方法public <T> T query(String statement, Object parameter);
}
  1. 创建nlc-mybatis\src\main\java\com\nlc\nlcmybatis\sqlsession\NlcExecutor.java
public class NlcExecutor implements Executor {//属性private NlcConfiguration nlcConfiguration =new NlcConfiguration();// 根据 sql 查找结果@Overridepublic <T> T query(String sql, Object parameter) {//得到连接ConnectionConnection connection = getConnection();//查询返回的结果集ResultSet set = null;PreparedStatement pre = null;try {pre = connection.prepareStatement(sql);//设置参数, 如果参数多, 可以使用数组处理.pre.setString(1, parameter.toString());set = pre.executeQuery();//把set数据封装到对象-monster//说明: 这里做了简化处理//认为返回的结果就是一个monster记录//完善的写法是一套反射机制.Monster monster = new Monster();//遍历结果集, 把数据封装到monster对象while (set.next()) {monster.setId(set.getInt("id"));monster.setName(set.getString("name"));monster.setEmail(set.getString("email"));monster.setAge(set.getInt("age"));monster.setGender(set.getInt("gender"));monster.setBirthday(set.getDate("birthday"));monster.setSalary(set.getDouble("salary"));}return (T) monster;} catch (Exception throwables) {throwables.printStackTrace();} finally {try {if (set != null) {set.close();}if (pre != null) {pre.close();}if (connection != null) {connection.close();}} catch (Exception throwables) {throwables.printStackTrace();}}return null;}//编写方法,通过NlcConfiguration对象,返回连接private Connection getConnection() {Connection connection =   nlcConfiguration.build("nlc_mybatis.xml");return connection;}
}

完成测试

  1. 修改nlc-mybatis\src\test\java\com\nlc\test\NlcMybatisTest.java , 增加测试方法
@Testpublic void query() {Executor executor = new NlcExecutor();Monster monster =executor.query("select * from monster where id=?", 1);System.out.println("monster-- " + monster);}
  1. 测试效果

😄总结

  1. 了解底层的机制可以帮助我们更好的学习,阅读优秀的源码可以增长我们的功力。
  2. 适当的debug可以解决我们的疑惑,底层是一个非常庞大的集成,把握主干就可以了。
  3. 过于追根究底只会影响自己的心绪,会耗费大量时间精力。
  4. 如果自己感兴趣的话,可以多研究一下,会发现其中的乐趣,点到即止。

文章到这里就结束了,如果有什么疑问的地方请指出,诸大佬们一起来评论区一起讨论😁
希望能和诸大佬们一起努力,今后我们一起观看感谢您的阅读🍻
如果帮助到您不妨3连支持一下,创造不易您们的支持是我的动力🤞

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

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

相关文章

(树) 剑指 Offer 27. 二叉树的镜像 ——【Leetcode每日一题】

❓剑指 Offer 27. 二叉树的镜像 难度&#xff1a;简单 请完成一个函数&#xff0c;输入一个二叉树&#xff0c;该函数输出它的镜像。 例如输入&#xff1a; 4/ \2 7/ \ / \1 3 6 9镜像输出&#xff1a; 4/ \7 2/ \ / \9 6 3 1示例 1&#xff1a; 输…

28_计算机网络(Computer Networks)基础

本篇介绍计算机网络的基础知识。 文章目录 1. 计算机网络历史2. 以太网" (Ethernet)2.1 以太网" (Ethernet)的简单形式及概念2.2 指数退避解决冲突问题2.3 利用交换机减少同一载体中设备2.4 互联网&#xff08;The Internet&#xff09;2.5 路由(routing)2.6 数据包…

基于峰谷分时电价引导下的电动汽车充电负荷优化(matlab代码)

目录 1 主要内容 峰谷电价优化 电动汽车充电负荷变化 2 部分代码 3 程序结果 1 主要内容 该程序基本复现《基于峰谷分时电价引导下的电动汽车充电负荷优化》&#xff0c;代码主要做的是基于NSGA-II的电动汽车充电负荷优化&#xff0c;首先&#xff0c;在研究电动汽车用户充…

重生之我要学C++第五天

这篇文章主要内容是构造函数的初始化列表以及运算符重载在顺序表中的简单应用&#xff0c;运算符重载实现自定义类型的流插入流提取。希望对大家有所帮助&#xff0c;点赞收藏评论&#xff0c;支持一下吧&#xff01; 目录 构造函数进阶理解 1.内置类型成员在参数列表中的定义 …

【云原生】Docker容器命令监控+Prometheus监控平台

目录 1.常用命令监控 docker ps docker top docker stats 2.weave scope 1.下载 2.安装 3.访问查询即可 3.Prometheus监控平台 1.部署数据收集器cadvisor 2.部署Prometheus 3.部署可视化平台Gragana 4.进入后台控制台 1.常用命令监控 docker ps [rootlocalhost ~…

重新审视MHA与Transformer

本文将基于PyTorch源码重新审视MultiheadAttention与Transformer。事实上&#xff0c;早在一年前博主就已经分别介绍了两者&#xff1a;各种注意力机制的PyTorch实现、从零开始手写一个Transformer&#xff0c;但当时的实现大部分是基于d2l教程的&#xff0c;这次将基于PyTorch…

opencv顺时针,逆时针旋转视频并保存视频

原视频 代码 import cv2# 打开视频文件 video cv2.VideoCapture(inference/video/lianzhang.mp4)# 获取原视频的宽度和高度 width int(video.get(cv2.CAP_PROP_FRAME_WIDTH)) height int(video.get(cv2.CAP_PROP_FRAME_HEIGHT))# 创建视频编写器并设置输出视频参数 fourcc …

【C++】类和对象(下)

1、初始化列表 初始化列表&#xff1a;以一个冒号开始&#xff0c;接着是一个以逗号分隔的数据成员列表&#xff0c;每个"成员变量"后面跟一个放在括号中的初始值或表达式。 class Date { public:Date(int year, int month, int day): _year(year), _month(month), _…

OSPF协议RIP协议+OSPF实验(eNSP)

本篇博客主要讲解单区域的ospf&#xff0c;多区域的仅作了解。 目录 一、OSPF路由协议概述 1.内部网关协议和外部网关协议 二、OSPF的应用环境 1.从以下几方面考虑OSPF的使用 2.OSPF的特点 三、OSPF重要基本概念 3.1&#xff0c;辨析邻居和邻接关系以及七种邻居状态 3…

【MySQL】索引与B+树

【MySQL】索引与B树 索引概念前导硬件软件方面 索引的理解单个page多个page引入B树B树的特征为什么B树做索引优于其他数据结构&#xff1f;聚簇索引与非聚簇索引辅助索引 索引的创建主键索引的创建和查看唯一键索引的创建和查看普通索引的创建和查看复合索引全文索引索引的其他…

js全端支持的深拷贝structuredClone

Jul 7, 2023 经过一年半的试用&#xff0c;structuredClone转正了&#xff0c;全端可以正式使用。 https://developer.mozilla.org/en-US/docs/Web/API/structuredClone

OpenHarmony开源鸿蒙学习入门 - 基于3.2Release 应用开发环境安装

OpenHarmony开源鸿蒙学习入门 - 基于3.2Release 应用开发环境安装 基于目前官方master主支&#xff0c;最新文档版本3.2Release&#xff0c;更新应用开发环境安装文档。 一、安装IDE&#xff1a; 1.IDE安装的系统要求 2.IDE下载官网链接&#xff08;IDE下载链接&#xff09; …

Modbus tcp转ETHERCAT在Modbus软件中的配置方法

Modbus tcp和ETHERCAT是两种不同的协议&#xff0c;这给工业生产带来了很大的麻烦&#xff0c;因为这两种设备之间无法通讯。但是&#xff0c;捷米JM-ECT-TCP网关的出现&#xff0c;却为这个难题提供了解决方案。 JM-ECT-TCP网关能够连接到Modbus tcp总线和ETHERCAT总线中&…

网络面试合集

传输层的数据结构是什么&#xff1f; 就是在问他的协议格式&#xff1a;UDP&TCP 2.1.1三次握手 通信前&#xff0c;要先建立连接&#xff0c;确保双方都是在线&#xff0c;具有数据收发的能力。 2.1.2四次挥手 通信结束后&#xff0c;会有一个断开连接的过程&#xff0…

Qsys介绍

文章目录 前言一、为什么需要Qsys1、简化了系统的设计流程2、Qsys涉及的技术 二、Qsys真身1、一种系统集成工具2、何为Nios II1、内核架构2、Nios II选型 三、Qsys设计涉及到的软件&工具四、总结五、参考资料 前言 Qsys是Altera下的一个系统集成工具&#xff0c;可用于搭建…

APP自动化测试-Python+Appium+Pytest+Allure框架实战封装(详细)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 pytest只是单独的…

JVM入门篇-JVM的概念与学习路线

JVM入门篇-JVM的概念与学习路线 什么是 JVM 定义 Java Virtual Machine - java 程序的运行环境&#xff08;java 二进制字节码的运行环境&#xff09; 好处 一次编写&#xff0c;到处运行自动内存管理&#xff0c;垃圾回收功能数组下标越界检查多态 比较 jvm jre jdk 常…

单片机第一季:零基础12——I2C和EEPROM

目录 1&#xff0c;EEPROM 2&#xff0c;I2C 2.1&#xff0c;I2C物理层 2.2&#xff0c;I2C协议层 3&#xff0c;AT24C02介绍 4&#xff0c;代码 1&#xff0c;EEPROM 为什么需要EEPROM&#xff1f; 单片机内部的ROM只能在程序下载时进行擦除和改写&#xff0c;但是…

护眼灯全光谱和减蓝光哪个好?推荐五款好用护眼台灯

如今&#xff0c;面临视力下降的问题越来越重视&#xff0c;护眼灯越来越成为人们日常生活中不可或缺的一部分&#xff0c;特别是在工作和学习中使用电脑、手机等电子设备时间较长的人群中。对于护眼灯来说&#xff0c;全光谱和减蓝光都是其主要功能之一&#xff0c;那么哪一种…

aws中opensearch 日志通(Centralized Logging with OpenSearch)2.0(一)

aws日志通2.0 实现全面的日志管理和分析功能 一体化日志摄取 &#xff1a;把aws服务器日志和应用日志传输到opensearch域中无代码日志处理 &#xff1a;在网页控制台中就可以实现数据处理开箱即用 &#xff1a;提供可视化模版&#xff08;nginx、HTTP server &#xff09; 架构…