Mybatis(十三) 底层源码分析

简介: Mybatis底层源码分析是对第十一部分的更深层次拓展(值得一看!!!)

Mybatis执行流程

流程图

在这里插入图片描述

mybaits 流程图的上半部分更多的是完成初始化
下半部分主要是实现增删改查操作

坐标添加

通过添加maven坐标 ,进而添加其jar包与源码 ,方便快捷 ; 也可以找到自己的mybatis项目 ,查看相关源码

<dependencies>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.2.8</version>
        </dependency>

源码分析

1. Configuration.xml

该配置文件是MyBatis 的全局配置文件,在这个文件中可以配置诸多项目。常用的内容是别名设置,拦截器设置等。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">
  <configuration>
       <properties resource="db.properties">
    </properties>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="com/bjsxt/mapper/UserMapper.xml"/>
    </mappers>

  </configuration>

Properties(属性)
将数据库连接参数单独配置在db.properties 中, 放在类路径下。这样只需要SqlMapConfig.xml 中加载db.properties 的属性值。这样在SqlMapConfig.xml 中就不需要对数据库连接参数硬编码。
将数据库连接参数只配置在db.properties 中,原因:方便对参数进行统一管理

Settings(全局配置参数)
Mybatis 全局配置参数,全局参数将会影响mybatis 的运行行为。比如:开启二级缓存、开启延迟加载

TypeAliases(类型别名)
类型别名是为Java 类型命名一个短的名字。它只和XML 配置有关, 只用来减少类完全限定名的多余部分

Plugins(插件)
MyBatis 允许你在某一点拦截已映射语句执行的调用。默认情况下,MyBatis 允许使用插件来拦截方法调用

Environments(环境集合属性对象)
MyBatis 可以配置多种环境。这会帮助你将SQL 映射应用于多种数据库之中。但是要记得一个很重要的问题:你可以配置多种环境,但每个数据库对应一个SqlSessionFactory。所以,如果你想连接两个数据库,你需要创建两个SqlSessionFactory 实例,每个数据库对应一个。

Environment(环境子属性对象)
ransactionManager(事务管理)
在MyBatis 中有两种事务管理器类型(也就是type=”[JDBC|MANAGED]”)
DataSource(数据源)

Mappers(映射器)
指定映射配置文件位置

<mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
<mapper url="file:///var/mappers/AuthorMapper.xml"/>
<mapper class="org.mybatis.builder.AuthorMapper"/>
<package name="org.mybatis.builder"/>

2. Mapper.xml

Mapper.xml 映射文件中定义了操作数据库的sql,每个sql 是一个statement,映射文件是mybatis 的核心

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.bjsxt.mapper.UsersMapper">
    <select id="selectUsers" resultType="com.bjsxt.pojo.User">
        select * from users
    </select>
</mapper>

ResultMap
Mybatis 中可以使用resultMap 完成高级输出结果映射。如果查询出来的列名和定义的pojo 属性名不一致,就可以通过定义一个resultMap 对列名和pojo 属性名之间作一个映射关系

Cache
开启二级缓存

Select
查询语句

Insert
插入语句

Update
更新语句

Delete
删除语句

3. Resources

Resources 工具类会从路径中加载资源,并返回一个输入流对象,对于资源文件的加载
提供了简易的使用方法。

如何进入Resource

在这段代码中 , 选中Resources , 通过鼠标 ctrl+鼠标左键进入 Resources类
InputStream inputStream = Resources.getResourceAsStream(resource);


import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Properties;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import com.bjsxt.mapper.UsersMapper;
import com.bjsxt.pojo.User;

public class Test {

    public static void main(String[] args) throws Exception {
            String resource = "SqlMapperClient.xml";
            
            //通过鼠标 ctrl+鼠标左键进入 Resources类
            InputStream inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
     
            SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.REUSE);
            try {
                //sqlSession.selectOne("");
                UsersMapper userMapper = sqlSession.getMapper(UsersMapper.class);
                List<User> list = userMapper.selectUsers();
                for (User user : list) {
                    System.out.printf(user.toString());
                }
            } finally {
                sqlSession.close();
            }
    }

}

方法解释

加载一个资源有很多方式:
对于简单的只读文本数据,加载为Reader。
对于简单的只读二进制或文本数据,加载为Stream。
对于可读写的二进制或文本文件,加载为File。
对于只读的配置属性文件,加载为Properties。
对于只读的通用资源,加载为URL。

按以上的顺序,Resources 类加载资源的方法如下(全都在本类,如下图的类结构):
Reader getResourceAsReader(String resource);
Stream getResourceAsStream(String resource);
File getResourceAsFile(String resource);
Properties getResourceAsProperties(String resource);
Url getResourceAsUrl(String resource);

在这里插入图片描述

4. SqlSessionFactoryBuilder

该类是SqlSessionFactory(会话工厂)的构建者类,之前描述的操作其实全是从这里面开启的,首先就是调用XMLConfigBuilder 类的构造器来创建一个XML 配置构建器对象,利用这个构建器对象来调用其解析方法parse()来完成Configuration 对象的创建,之后以这个配置对象为参数调用会话工厂构建者类中的build(Configuration config) 方法来完成SqlSessionFactory(会话工厂)对象的构建。

在这里插入图片描述

5. XMLConfigBuilder

该类是XML 配置构建者类,是用来通过XML 配置文件来构建Configuration 对象实例,构建的过程就是解析Configuration.xml 配置文件的过程,期间会将从配置文件中获取到的指定标签的值逐个添加到之前创建好的默认Configuration 对象实例中

在这里插入图片描述

6. Configuration

该对象是Mybatis 的上下文对象,实例化这个类的目的就是为了使用其对象作为项目全局配置对象,这样通过配置文件配置的信息可以保存在这个配置对象中,而这个配置对象在创建好之后是保存在JVM 的Heap 内存中的,方便随时读取。不然每次需要配置信息的时候都要临时从磁盘配置文件中获取,代码复用性差的同时,也不利于开发 (上下文对象 ,保存配置信息)
在这里插入图片描述

7. DefaultSqlSessionFactory

SqlsessionFactory 该接口是会话工厂, 是用来生产会话的工厂接口,DefaultSqlSessionFactory 是其实现类,是真正生产会话的工厂类,这个类的实例的生命周期是全局的,它只会在首次调用时生成一个实例(单例模式),就一直存在直到服务器关闭。

在这里插入图片描述

8. Executor

执行器接口,SqlSession 会话是面向程序员的,而内部真正执行数据库操作的却是Executor 执行器,可以将Executor 看作是面向MyBatis 执行环境的,SqlSession 就是门面货,Executor 才是实干家。通过SqlSession 产生的数据库操作,全部是通过调用Executor 执行器来完成的。
Executor 是跟SqlSession 绑定在一起的,每一个SqlSession 都拥有一个新的Executor 对象,由Configuration 创建。

在这里插入图片描述

继承结构

在这里插入图片描述
在这里插入图片描述

BaseExecutor

SimpleExecutor:
每执行一次update 或select,就开启一个Statement 对象,用完立刻关闭Statement 对象。(可以是Statement 或PrepareStatement 对象)

在这里插入图片描述
ReuseExecutor:
执行update 或select,以sql 作为key 查找Statement 对象,存在就使用,不存在就创建,用完后,不关闭Statement 对象,而是放置于Map<String, Statement>内,供
下一次使用。(可以是Statement 或PrepareStatement 对象)
在这里插入图片描述
BatchExecutor:
执行update(没有select,JDBC 批处理不支持select),将所有sql 都添加到批处理中(addBatch()),等待统一执行(executeBatch()),它缓存了多个Statement对象,每个Statement 对象都是addBatch()完毕后,等待逐一执行

在这里插入图片描述

CachingExecutor

先从缓存中获取查询结果,存在就返回,不存在,再委托给Executor delegate 去数据库取,delegate 可以是上面任一的SimpleExecutor、ReuseExecutor、BatchExecutor。RoutingStatementHandler,这是一个封装类,它不提供具体的实现,只是根据Executor的类型,创建不同的类型StatementHandler。
在这里插入图片描述

9. StatementHandler

该类是Statement 处理器,封装了Statement 的各种数据库操作方法execute(),可见MyBatis 其实就是将操作数据库的JDBC 操作封装起来的一个框架,同时还实现了ORM 罢
了。

在这里插入图片描述

10. ResultSetHandler

结果集处理器,如果是查询操作,必定会有返回结果,针对返回结果的操作,就要使用
ResultSetHandler 来进行处理,这个是由StatementHandler 来进行调用的。这个处理器的作用
就是对返回结果进行处理。

在这里插入图片描述

相关文章
|
7月前
|
SQL Java 数据库连接
Mybatis源码分析系列之第三篇:Mybatis的操作类型对象
Mybatis源码分析系列之第三篇:Mybatis的操作类型对象
|
SQL XML Java
源码分析系列教程(08) - 手写MyBatis(注解版)
源码分析系列教程(08) - 手写MyBatis(注解版)
114 0
|
2月前
|
Java 数据库连接 mybatis
Springboot整合Mybatis,MybatisPlus源码分析,自动装配实现包扫描源码
该文档详细介绍了如何在Springboot Web项目中整合Mybatis,包括添加依赖、使用`@MapperScan`注解配置包扫描路径等步骤。若未使用`@MapperScan`,系统会自动扫描加了`@Mapper`注解的接口;若使用了`@MapperScan`,则按指定路径扫描。文档还深入分析了相关源码,解释了不同情况下的扫描逻辑与优先级,帮助理解Mybatis在Springboot项目中的自动配置机制。
142 0
Springboot整合Mybatis,MybatisPlus源码分析,自动装配实现包扫描源码
|
7月前
|
存储 缓存 Java
探秘MyBatis缓存原理:Cache接口与实现类源码分析
探秘MyBatis缓存原理:Cache接口与实现类源码分析
109 2
探秘MyBatis缓存原理:Cache接口与实现类源码分析
|
7月前
|
SQL Java 数据库连接
MyBatis源码篇:mybatis拦截器源码分析
MyBatis源码篇:mybatis拦截器源码分析
|
7月前
|
缓存 Java 数据库连接
|
7月前
|
SQL Java 数据库连接
|
7月前
|
设计模式 SQL Java
Mybatis源码分析系列之第四篇:Mybatis中代理设计模型源码详解
Mybatis源码分析系列之第四篇:Mybatis中代理设计模型源码详解
|
7月前
|
存储 SQL Java
Mybatis源码分析系列之第二篇:Mybatis的数据存储对象
Mybatis源码分析系列之第二篇:Mybatis的数据存储对象
|
7月前
|
Java 关系型数据库 数据库连接
Mybatis源码分析系列之第一篇:回顾一下MyBatis的使用
Mybatis源码分析系列之第一篇:回顾一下MyBatis的使用