转载

Mybatis进阶笔记03:架构概述与基本执行流程梳理

  1. Mybatis的架构概述
  2. 结合源码结构Mybatis的基本执行流程

一、Mybatis的架构概述

  1. Mybatis的架构概览如图所示:
    Mybatis进阶笔记03:架构概述与基本执行流程梳理
  2. 第一层:SQLsession,直接对外暴露,也是我们最常用的组件:
    <?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"></transactionManager>
                <dataSource type="POOLED">
                    <property name="driver" value="com.mysql.jdbc.Driver"></property>
                    <property name="url" value="jdbc:mysql://localhost/mybatis_test"></property>
                    <property name="username" value="root"></property>
                    <property name="password" value="111111"></property>
                </dataSource>
            </environment>
        </environments>
        <!--加载映射文件-->
        <mappers>
            <mapper resource="cn/zephyr/mapper/SysUserMapper.xml"></mapper>
        </mappers>
    </configuration>
    复制代码
    // 根据配置文件获取到SqlSessionFactory
        InputStream configFile = new FileInputStream("./src/main/resources/mybatis-conf.xml");
        // 根据SqlSessionFactory获取sqlSession
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(configFile);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 在sqlSession中获取Mapper
        SysUserMapper mapper = sqlSession.getMapper(SysUserMapper.class);
        // 执行SQL查询,获取结果
        List<SysUser> sysUsers = mapper.queryList();
        System.err.println(Arrays.asList(sysUsers));
    复制代码
    Mybatis进阶笔记03:架构概述与基本执行流程梳理
  3. 第二层:核心功能封装
    1. 配置parsing
    2. Parameter Mapping:查询条件的解析
    3. Sql Parsing:负责XxxMapper.xml或者基于注解(“@Select”等)的sql解析
    4. Executor:负责真正的SQL执行
    5. ResultSet Mapping:结果集映射
    6. Plugins:提供插件支持
  4. 第三层:最底层的功能
    1. 数据源:提供数据源支持
    2. 缓存:提供缓存支持
    3. Binding:负责将XxxMapper.java与XxxMapper.xml做双向绑定
    4. 日志:日志输出sql语句的执行日志,内部使用了代理模式,此处略加说明
      1. 抽象类是BaseJdbcLogger,同级包下有4个子类进行集成
        Mybatis进阶笔记03:架构概述与基本执行流程梳理
      2. 以ConnectionLogger为例,各个Executor在执行sql之前获取到的connection,其实是connection的代理对象,通过代理类实现建立连接时的日志打印:
        Mybatis进阶笔记03:架构概述与基本执行流程梳理
      3. 再通过配置项,实现对打印日志的开关控制:
        Mybatis进阶笔记03:架构概述与基本执行流程梳理
    5. 资源加载
    6. 类型转换:负责将Java的数据类型与SQL的数据类型之间的互相转换
    7. 事务管理:Mybatis提供了轻量级的事务管理(很少用,实际项目使用时,通常将Mybatis集成到Spring,这种情况下,事务将由spring统一管理)
    8. 反射:封装了Java的反射方法作为工具类,起到了简化代码的作用
    9. parsing:负责XxxMapper.xml或者基于注解(“@Select”等)的sql解析(以面向对象的思想来看待mybatis,XxxMapper.java是一个动作,对应的结果实体对应到实际的数据库表是一个名词)
      Mybatis进阶笔记03:架构概述与基本执行流程梳理

二、结合源码结构Mybatis的基本执行流程

1. 先说结论

  1. 再贴一下原生使用mybatis的示例代码(为了简单,只使用了一个xml配置文件,相关的Java代码都写在单元测试用,pom直接使用了mybatis.springboot.starter):
    <?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"></transactionManager>
                <dataSource type="POOLED">
                    <property name="driver" value="com.mysql.jdbc.Driver"></property>
                    <property name="url" value="jdbc:mysql://localhost/mybatis_test"></property>
                    <property name="username" value="root"></property>
                    <property name="password" value="111111"></property>
                </dataSource>
            </environment>
        </environments>
        <!--加载映射文件-->
        <mappers>
            <mapper resource="cn/zephyr/mapper/SysUserMapper.xml"></mapper>
        </mappers>
    </configuration>
    复制代码
    // 1. 读取配置文件
        InputStream configFile = new FileInputStream("./src/main/resources/mybatis-conf.xml");
        // 2. 根据配置文件获取到SqlSessionFactory
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(configFile);
        // 3. 根据SqlSessionFactory获取sqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 4. 在sqlSession中获取Mapper
        SysUserMapper mapper = sqlSession.getMapper(SysUserMapper.class);
        // 5. 执行SQL查询,获取结果
        List<SysUser> sysUsers = mapper.queryList();
        System.err.println(Arrays.asList(sysUsers));
    复制代码
  2. 结论:
    <mappers>
    

2. 结论验证:

  1. 第一步:加载配置文件到IO流;
    InputStream configFile = new FileInputStream("./src/main/resources/mybatis-conf.xml");
    复制代码
  2. 第二步:解析配置文件;
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(configFile);
    复制代码
    这一步主要做的事情就是根据配置文件获取所有的Mapper.xml,从而获取Mapper接口类,并以Mapper接口类为键,对应的代理工厂对象为值,存储到一个Mapper容器(knownMappers)中。这一步整体的代码执行流程如下图所示:
    Mybatis进阶笔记03:架构概述与基本执行流程梳理
  3. 第三步:获取sqlSession(此处暂不展开分析);
    SqlSession sqlSession = sqlSessionFactory.openSession();
    复制代码
  4. 第四步:根据Mapper接口类获取实现类(动态代理生成的对象);
    sqlSession.getMapper(SysUserMapper.class);
    复制代码
    这一步就根据接口类,从之前的容器(knownMappers)中拿到对应的代理工厂对象,生成对应的代理对象并将其返回,这一步整体的代码执行流程如下:
    Mybatis进阶笔记03:架构概述与基本执行流程梳理
    通过断点可以看到,最终拿到的对象实现类对象是一个代理对象
    Mybatis进阶笔记03:架构概述与基本执行流程梳理
  5. 第五步:调用Executor执行sql
    List<SysUser> sysUsers = mapper.queryList();
    复制代码

欢迎访问我的个人博客

原文  https://juejin.im/post/5d261d256fb9a07edf276e17
正文到此结束
Loading...