Mybatis源码1JDBC->mybatis主要流程->mybatis Excutor简介
===
一丶mybatis概述
MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
二丶传统JDBC操作
JDBC的全称是Java数据库连接(Java Database connect),它是一套用于执行SQL语句的Java API。应用程序可通过这套API连接到关系数据库,并使用SQL语句来完成对数据库中数据的查询、更新和删除等操作
mybatis让我们重复的jdbc操作中解放开来 ,但是不能被工具的便捷蒙蔽了双眼,让我们从锤子开始
public List<Student> selectAllStudent() {
try {
//注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
} catch (Exception e) {
}
ArrayList<Student> list = new ArrayList<>();
Connection connection = null;
PreparedStatement statement = null;
ResultSet resultSet = null;
try {
//获取连接
connection = DriverManager.getConnection("url","username","password");
//创建statement
statement = connection.prepareStatement("select * from student");
//执行查询,得到结果集
resultSet = statement.executeQuery();
//结果集到对象的映射
while (resultSet.next()) {
int id = resultSet.getInt("id");
String name = resultSet.getString("name");
boolean sex = resultSet.getBoolean("sex");
Student temp = Student.builder()
.id(id)
.name(name)
.sex(sex)
.build();
list.add(temp);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
//关闭资源
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
return list;
}
注册驱动
Class.forName,利用反射获取驱动的class,实际执行了Driver的静态代码块内容
//将mysql的驱动注册到DriverManager
static {
try {
//把driver加载到 DriverManager的registeredDrivers 集合中去
java.sql.DriverManager.registerDriver(new Driver());
} catch (SQLException E) {
throw new RuntimeException("Can't register driver!");
}
}
/**
* 空白的构造函数
*
* @throws SQLException
* if a database error occurs.
*/
public Driver() throws SQLException {
//下面说明了 使用Class.forName
// Required for Class.forName().newInstance()
}
获取连接
DriverManager.getConnection() 方法用于获得试图建立到指定数据库 URL 的连接。DriverManager 试图从已注册的 JDBC 驱动程序集中选择一个适当的驱动程序(可能存在多个已经注册的连接)
这里面的逻辑是,调用了
return (getConnection(url, info, Reflection.getCallerClass()));
//Reflection.getCallerClass()获取调用方法的类
//如果当前调用方为null 那么从当前线程获取类加载器
//Thread.currentThread().getContextClassLoader()
//遍历每一个驱动,返回第一个合适的驱动
构造Statement
用于执行静态SQL语句并返回其生成的结果的对象。
PrepareStatement: 表示预编译的SQL语句的对象,SQL语句已预编译并存储在
PreparedStatement对象中。 然后可以使用该对象多次有效地执行此语句执行查询,得到结果集,结果集映射到对象
ResultSet
表示数据库结果集的数据表,通常通过执行查询数据库的语句生成。
ResultSet对象保持一个光标指向其当前的数据行。 最初,光标位于第一行之前。next方法将光标移动到下一行,并且由于在ResultSet对象中没有更多行时返回false,因此可以在while循环中使用循环来遍历结果集。关闭连接
三丶mybatis的简单使用和大致执行流程
//mybatis全局配置
String resource = "com/cuzz/mybatislearn/mybatis.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
//根据配置拿到sqlSessionFactory 【工厂模式】
SqlSessionFactory sqlSessionFactory = new
SqlSessionFactoryBuilder().build(inputStream);
//获取SqlSession 该对象中包含了执行SQL语句的所有方法【门面模式】
SqlSession sqlSession = sqlSessionFactory.openSession();
//获取代理后的mapper
StudentDao mapper = sqlSession.getMapper(StudentDao.class);
//执行
List<Student> students = mapper.listAll();

(1)读取MyBatis的配置文件。mybatis-config.xml为MyBatis的全局配置文件,用于配置数据库连接信息。
(2)加载映射文件。映射文件即SQL映射文件,该文件中配置了操作数据库的SQL语句,需要在MyBatis配置文件mybatis-config.xml中加载。mybatis-config.xml 文件可以加载多个映射文件,每个文件对应数据库中的一张表。
(3)构造会话工厂。通过MyBatis的环境配置信息构建会话工厂SqlSessionFactory。
(4)创建会话对象。由会话工厂创建SqlSession对象,该对象中包含了执行SQL语句的所有方法。
(5)Executor执行器。MyBatis底层定义了一个Executor接口来操作数据库,它将根据SqlSession传递的参数动态地生成需要执行的SQL语句,同时负责查询缓存的维护。
(6)MappedStatement对象。在Executor接口的执行方法中有一个MappedStatement类型的参数,该参数是对映射信息的封装,用于存储要映射的SQL语句的id、参数等信息。
(7)输入参数映射。输入参数类型可以是Map、List等集合类型,也可以是基本数据类型和POJO类型。输入参数映射过程类似于JDBC对preparedStatement对象设置参数的过程。
(8)输出结果映射。输出结果类型可以是Map、List等集合类型,也可以是基本数据类型和POJO类型。输出结果映射过程类似于JDBC对结果集的解析过程。z
四丶mybatis中的执行器
mybatis的执行器,是mybatis最为关键的地方(相比于扫描mapper得到全局配置)

1.Executor接口
- 该接口提供了改和查的基本功能(数据库的删除插入本质也是更新,其实对应了statement中的executeUpdate和executeQuery方法)
- 提交和回滚
- 缓存相关方法
- 批处理刷新
- 执行器关闭
- 延迟加载
2.BaseExecutor
对Executor中的接口中的大部分方法进行了通用的实现,并且可以通过配置文件,或者手动指定执行器类型来让mybatis使用具体执行器实现(这里说的实现只有BatchExcutor,SimpleExecutor,ReuseExcutor),还提供了三个抽象方法(如下)让子类实现
- doUpdate
- doFlushStatements
- doQuery
3.SimpleExecutor
简单执行器,是 MyBatis 中默认使用的执行器,对BaseExecutor中的方法进行了简单的实现,(根据配置获取连接,根据连接获取Statement,执行sql,结果集映射)每执行一次 update 或 select,就开启一个 Statement 对象,用完就直接关闭 Statement 对象
4.BatchExecutor
主要应对批量更新,插入,删除,一次向数据库发送多个SQL语句从而减少通信开销,从而提高性能。(对查找不生效)
批量处理允许将相关的SQL语句分组到批处理中,并通过对数据库的一次调用来提交它们,一次执行完成与数据库之间的交互。需要注意的是:JDBC中的批处理只支持 insert、update 、delete 等类型的SQL语句,不支持select类型的SQL语句。
5.ReuseExecutor
ReuseExecutor 不同于 SimpleExecutor 的地方在于 ReuseExecutor 维护了 Statement 缓存
ReuseExecutor顾名思义就是重复使用执行,其定义了一个Map<String, Statement>,将执行的sql作为key,将执行的Statement作为value保存,这样执行相同的sql时就可以使用已经存在的Statement,就不需要新创建了,从而避免SimpleExecutor这样多次进行参数拼接生成statement以提高性能
6.CachingExecutor
CachingExecutor没有继承BaseExecutor,CachingExecutor 不具备 Executor 执行器功能,CachingExecutor 是一个装饰器, Mybatis 采用装饰者模式对 Executor 执行器提供了功能增强。CachingExecutor装饰器能够使得被装饰的Executor 具备二级缓存功能
附录
为什么注册驱动需要使用Class.forName
Class.forName(String)会加载类,并且并且执行类初始化,会执行driver中的静态代码块,静态代码块中进行了驱动的注册,
Class.forName,和ClassLoader.loadClass的区别
- Class.forName(String): 加载类,并且执行类初始化,可以通过Class.forName(String, boolean, ClassLoader)第二个参数来仅仅加载类不执行初始化
- ClassLoader.loadClass(String): 仅仅加载类,不执行类初始化
注册驱动的方式有哪些
在java 6中,引入了service provider的概念,即可以在配置文件中配置service(可能是一个interface或者abstract class)的provider(即service的实现类)。配置路径是:/META-INF/services/下面。
而java.sql.DriverManager也添加了对此的支持,因此,在JDK6中,DriverManager的查找Driver的范围为:
1)system property “jdbc.drivers” 中配置的Driver值;
2)用户调用Class.forName()注册的Driver
3)service provider配置文件java.sql.Driver中配置的Driver值。
因此,在jdk6中,其实是可以不用调用Class.forName来加载mysql驱动的,因为mysql的驱动程序jar包中已经包含了java.sql.Driver配置文件,并在文件中添加了com.mysql.jdbc.Driver.但在JDK6之前版本,还是要调用这个方法。
Mybatis源码1JDBC->mybatis主要流程->mybatis Excutor简介的更多相关文章
- Mybatis源码学习第六天(核心流程分析)之Executor分析
今Executor这个类,Mybatis虽然表面是SqlSession做的增删改查,其实底层统一调用的是Executor这个接口 在这里贴一下Mybatis查询体系结构图 Executor组件分析 E ...
- mybatis源码学习(四)--springboot整合mybatis原理
我们接下来说:springboot是如何和mybatis进行整合的 1.首先,springboot中使用mybatis需要用到mybatis-spring-boot-start,可以理解为mybati ...
- Mybatis源码学习第六天(核心流程分析)之Executor分析(补充)
补充上一章没有讲解的三个Executor执行器; 还是贴一下之前的代码吧;我发现其实有些分析注释还是写在代码里面比较好,方便大家理解,之前是我的疏忽,不好意思 @Override public < ...
- springboot集成mybatis源码分析-启动加载mybatis过程(二)
1.springboot项目最核心的就是自动加载配置,该功能则依赖的是一个注解@SpringBootApplication中的@EnableAutoConfiguration 2.EnableAuto ...
- MyBatis源码分析-MyBatis初始化流程
MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以对配置和原生Map使用简 ...
- MyBatis源码分析-SQL语句执行的完整流程
MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以对配置和原生Map使用简 ...
- MyBatis 源码篇-SQL 执行的流程
本章通过一个简单的例子,来了解 MyBatis 执行一条 SQL 语句的大致过程是怎样的. 案例代码如下所示: public class MybatisTest { @Test public void ...
- MyBatis 源码分析 - 缓存原理
1.简介 在 Web 应用中,缓存是必不可少的组件.通常我们都会用 Redis 或 memcached 等缓存中间件,拦截大量奔向数据库的请求,减轻数据库压力.作为一个重要的组件,MyBatis 自然 ...
- MyBatis 源码分析 - 映射文件解析过程
1.简介 在上一篇文章中,我详细分析了 MyBatis 配置文件的解析过程.由于上一篇文章的篇幅比较大,加之映射文件解析过程也比较复杂的原因.所以我将映射文件解析过程的分析内容从上一篇文章中抽取出来, ...
- MyBatis 源码分析 - 配置文件解析过程
* 本文速览 由于本篇文章篇幅比较大,所以这里拿出一节对本文进行快速概括.本篇文章对 MyBatis 配置文件中常用配置的解析过程进行了较为详细的介绍和分析,包括但不限于settings,typeAl ...
随机推荐
- 前端三件套系例之JS——JavaScript内置方法
文章目录 1.Number 1-1 属性 1-2 方法 2.String 2-1 属性 2-2 方法 2-3 代码 3Array 3-1 创建数组 3-2 数组特点 3-3 数组的遍历(迭代) 34 ...
- 从内核世界透视 mmap 内存映射的本质(源码实现篇)
本文基于内核 5.4 版本源码讨论 通过上篇文章 <从内核世界透视 mmap 内存映射的本质(原理篇)>的介绍,我们现在已经非常清楚了 mmap 背后的映射原理以及它的使用方法,其核心就是 ...
- Java并发编程和多线程的区别
并发编程: 并发编程是一种编程范式,它关注的是编写能够正确和高效处理多个并发任务的程序.并发编程不仅包括多线程,还包括了处理多个独立任务的各种技术和模式,如进程.协程.分布式编程等.并发编程的目标是实 ...
- 快速展示原型之Minimal API开发
Minimal API官网地址: https://learn.microsoft.com/zh-cn/aspnet/core/fundamentals/minimal-apis/security?vi ...
- 欢迎来到hitcorgi,corgi居然被抢注了
1 #include <iostream> 2 3 using namespace std; 4 5 int main() 6 { 7 cout << "Hello ...
- windows 下终止nginx 进程 重新启动nginx
进入cmd 输入一下命令 删除nginx所有进程 taskkill /f /t /im nginx.exe
- Calendar日历类型常见方法(必看!!)
Hi i,m JinXiang 前言 本篇文章主要介绍Calendar日历类型的几种常见方法以及部分理论知识 欢迎点赞 收藏 留言评论 私信必回哟 博主收将持续更新学习记录获,友友们有任何问题可以在 ...
- notify为什么会引发超时,notify和notifyAll的区别
notify为什么会引发超时,notify和notifyAll的区别 每个同步对象都有对应的monitor,首先了解下monitor的内部结构. 1.monitor结构 Owner:指向拥有该同步对象 ...
- Go切片是值传递还是引用传递?
Go没有引用传递和引用类型!!! 很多人有个误区,认为涉及Go切片的参数是引用传递,或者经常听到Go切片是引用类型这种说法,今天我们就来说一下方面的问题. 什么是值传递? 将实参的值传递给形参,形参是 ...
- Java自定义ClassLoader实现插件类隔离加载 - 原理篇
书接上回 在 Java自定义ClassLoader实现插件类隔离加载文章中,我们通过 自定义ClassLoader + 插件独立打包引入的方式,实现了同依赖不同版本的隔离加载 这次咱们来分析下具体实现 ...