MyBatis系列1_介绍和流程分析

287 阅读3分钟

MyBatis介绍

以前都是对MyBatis的使用,因为最近开发扩展组件经常要跟MyBatis打交道,需要在一定条件下修改MyBatis的相关执行逻辑,因此对MyBatis的源码研究了一遍,记一下笔记

我们都清楚MyBatis是一个非常强大的半自动化ORM框架,它实现的核心原理是动态代理接口+Mapper.xml实现了ORM操作,为什么说它是半自动化?这是因为它无法摆脱SQL语句的编写,但是又支持Java代码面向接口调用,减少了实现类的编写,虽然在自动化不如Hibernate,但是因为保留了sql语句编写功能,在灵活度和对sql性能优化层面大大优于Hibernate。现在MyBatis算是在ORM框架中使用最多的。

使用示例

单独使用

    private static SqlSessionFactory sqlSessionFactory;

    //使用mybatis第一步,获取sqlSessionFactory对象
    static {
        try {
            String resource = "mybatis-test/mybatis-config-test.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public static SqlSession getSqlSession(){
        return sqlSessionFactory.openSession();
    }

    public static void main(String[] args) {
        SysConfigMapper mapper = getSqlSession().getMapper(SysConfigMapper.class);
        List<SysConfig> sysConfigs = mapper.selectConfigList(new SysConfig());
        System.out.println();
    }

结合SpringBoot使用

在application.yaml中添加配置信息,SpringBoot会自动根据dataSource配置启动MyBatis

# MyBatis
mybatis:
    # 搜索指定包别名
    typeAliasesPackage: com.ruoyi.**.domain
    # 配置mapper的扫描,找到所有的mapper.xml映射文件
    mapperLocations: classpath*:mapper/**/*Mapper.xml
    # 加载全局的配置文件
    configLocation: classpath:mybatis/mybatis-config.xml

MyBatis-config.xml配置样例

<?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>
    <!-- 全局参数 -->
    <settings>
        <!-- 使全局的映射器启用或禁用缓存 -->
        <setting name="cacheEnabled"             value="true"   />
        <!-- 允许JDBC 支持自动生成主键 -->
        <setting name="useGeneratedKeys"         value="true"   />
        <!-- 配置默认的执行器.SIMPLE就是普通执行器;REUSE执行器会重用预处理语句(prepared statements);BATCH执行器将重用语句并执行批量更新 -->
        <setting name="defaultExecutorType"      value="SIMPLE" />
        <!-- 指定 MyBatis 所用日志的具体实现 -->
        <setting name="logImpl"                  value="SLF4J"  />
        <!-- 使用驼峰命名法转换字段 -->
        <!-- <setting name="mapUnderscoreToCamelCase" value="true"/> -->
    </settings>
    <typeAliases>
        <package name="com.ruoyi.system.domain"/>
    </typeAliases>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>
    <!--每一个Mapper.XML都需要在Mybatis核心配置文件中注册!-->
    <mappers>
        <mapper resource="mybatis-test/SysConfigMapper.xml"/>
    </mappers>
</configuration>

MyBatis工作流程分析

2023-04-16-17-32-08-image.png

先简单分析一下MyBatis的工作流程,后面再深入分析实现细节。

  1. 获取配置信息

    在我们使用过程中,主要有两种方式使用MyBatis分别是:单独使用MyBatis框架,使用SpringBoot集成。(还有使用Spring单独集成的,现在因为基本上用Spring都用SpringBoot了,所以就不单独列出来了)

    这一步骤的主要目的是生成Configuration实例,并设置相关配置信息,这个类相当重要,它贯穿了整个MyBatis的生命周期,类似Spring框架的Context

    单独使用MyBatis框架,一般都是创建mybatis-config.xml然后将配置信息配置到xml中,通过读取xml,然后解析xml生成Configuration对象,核心API是XMLConfigBuilder#parse

    与SpringBoot集成使用,还是SpringBoot自动配置规则,一个xxxAutoConfiguration+xxxProperties搭配实现自动配置。对MyBatis也不例外,MybatisAutoConfiguration+MybatisProperties获取配置信息 然后用Spring的FactoryBean组件实现SqlSessionFactoryBean进行创建SqlSessionFactory。

    并且SpringBoot相对强大点的是,你不止可以通过它提供的MybatisProperties在application.yml中设置MyBatis信息配置信息,还可以通过mybatis.configLocation配置引入独立的mybatis-config.xml配置,来兼容某些全局配置和减少适配以前独立使用mybatis框架配置信息。

    也是在这一步将mapper.xml解析成了相关MappedStatement,用于描述mapper.xml中写的sql语句,包括每个statement的返回值,sql内容等。

  2. 创建SqlSessionFactory

    创建SqlSessionFactory一般没有特殊需求的都是使用的是MyBatis的默认SqlSessionFactoryBuilder#build(org.apache.ibatis.session.Configuration)。

    独立使用:

    String resource = "mybatis-test/mybatis-config-test.xml";
    InputStream inputStream = Resources.getResourceAsStream(resource);
    sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    

    SpringBoot中的SqlSessionFactoryBean#buildSqlSessionFactory

    // SqlSessionFactoryBean的全局属性
    private SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
    // SqlSessionFactoryBean#buildSqlSessionFactory的返回最后一步
    return this.sqlSessionFactoryBuilder.build(targetConfiguration);
    
  3. 获取Session

    获取Session,org.apache.ibatis.session.SqlSessionFactory#openSession(),主要功能是通过dataSource获取一个会话session来执行sql语句。这一步会选择相应的ExecutorType执行具体的语句,以及相关事务操控。一般来说都是使用的DefaultSqlSession如果我们不想使用Mapper.xml,则在这个类里面还提供了一些直接通过方法调用传sql语句执行的一些API。

    DefaultSqlSession有个核心方法,也就是getMapper方法,该方法会调用Configuration的getMapper方法,然后通过MapperRegistry动态生成Mapper的代理类。

  4. 生成代理对象MapperProxy

    生成代理类是MapperRegistry来进行生成的,有个专门生成的工厂:MapperProxyFactory,生成的代理类为MapperProxy

  5. 执行Mapper代理对象

    MapperProxy#invoke,调用Executor执行