文章目录

前言

MyBatis-Plus 是一个增强版的 MyBatis 框架,它在 MyBatis 的基础上增加了许多实用的功能,例如乐观锁插件、字段自动填充、分页插件、条件构造器和 SQL 注入器等。MyBatis-Plus 允许开发者无需编写 XML 文件,直接通过继承 BaseMapper 接口的类来完成数据库操作。

第一章:MyBatis-Plus 核心组件与工作流程

MyBatis-Plus 在 MyBatis 的基础上增加了诸多功能,如乐观锁、自动填充字段、分页等。它的核心组件包括 SQL 注入器、主键生成器等,这些组件协同工作,构成了 MyBatis-Plus 的强大功能。

1.1 MyBatis-Plus 与 MyBatis 的关系和优势

对比项MyBatisMyBatis-Plus
简介半自动的持久层框架,提供了一系列 API 用于数据库交互增强版 MyBatis 框架,继承所有特性并提供更多便捷功能
关系完全兼容 MyBatis,在其基础上增加更多功能
CRUD 操作需要手动编写 SQL 语句和映射 XML提供简洁 API,简化 CRUD 操作
XML 配置需要编写 XML 文件配置 SQL 映射无需 XML 配置,支持注解或 Java API
查询构建手动编写 SQL,不支持复杂查询的简化构建提供条件构造器,简化复杂查询条件的构建
分页功能需要手动处理分页逻辑内置分页插件,方便实现分页
乐观锁不直接支持,需要手动实现支持乐观锁机制,简化并发控制
字段自动填充不支持支持字段自动填充,如创建时间、更新时间
性能依赖手动优化 SQL 语句性能优化,如 SQL 语句缓存和重用
可扩展性高度可扩展,支持自定义插件和拦截器保持高度可扩展性,支持自定义开发
开发效率较高,但需要较多手动配置更高,简化了常见操作和配置
适用场景适合需要精细控制 SQL 语句的场景适合快速开发,简化数据库操作的场景

MyBatis-Plus 作为一个增强版的 MyBatis 框架,它不仅继承了 MyBatis 的所有优点,还在此基础上提供了更多现代化、便捷的功能。对于需要快速开发且希望简化数据库操作的 Java 应用来说,MyBatis-Plus 是一个非常优秀的选择。

1.2 核心组件概览:Mapper、SQL 注入器、主键生成器等

MyBatis-Plus 作为一个功能丰富的持久层框架,拥有一些核心组件来支持其强大的功能。以下是 MyBatis-Plus 中一些关键的核心组件:

1. Mapper

Mapper 在 MyBatis-Plus 中扮演着至关重要的角色,它是数据库操作的入口。通过继承 BaseMapper 接口,开发者可以无需编写 XML 映射文件,直接通过 Java API 来执行数据库操作。Mapper 接口方法与 SQL 语句之间的映射是通过动态代理和运行时分析来实现的。

2. SQL 注入器 (SqlInjector)

SQL 注入器负责将 Mapper 接口中定义的方法注入为可执行的 SQL 语句。MyBatis-Plus 提供了默认的 SQL 注入器 DefaultSqlInjector,它能够处理大多数基本的 SQL 映射需求。此外,开发者可以根据特定需求自定义 SQL 注入器,以支持复杂的 SQL 语句生成。

3. 主键生成器 (KeyGenerator)

MyBatis-Plus 的主键生成器用于自动生成数据库表的主键值。这在插入新记录时特别有用,特别是当数据库表使用自增主键或触发器生成主键时。通过实现 IKeyGenerator 接口,开发者可以自定义主键生成策略。

4. 乐观锁插件 (Pessimistic Lock Interceptor)

乐观锁插件是 MyBatis-Plus 提供的一个用于处理并发更新的功能组件。它通过在 SQL 更新语句中添加版本号或时间戳来实现乐观锁机制,从而避免在数据更新时发生冲突。

5. 字段自动填充功能 (MetaObjectHandler)

字段自动填充功能允许开发者自定义字段的自动填充策略,例如自动填充创建时间或更新时间。通过实现 MetaObjectHandler 接口,可以在插入或更新记录时自动填充这些字段。

6. 分页插件 (PaginationInterceptor)

分页插件是 MyBatis-Plus 中用于处理分页查询的组件。通过 PaginationInterceptor,开发者可以轻松地对查询结果进行分页处理,而无需手动编写分页 SQL。

7. 条件构造器 (Wrapper)

条件构造器是 MyBatis-Plus 提供的一个强大工具,用于构建复杂的查询条件。通过链式调用,开发者可以方便地添加、组合各种查询条件,简化了复杂查询的构建过程。

8. 性能分析插件 (PerformanceInterceptor)

性能分析插件可以帮助开发者分析和诊断 SQL 语句的性能问题。通过 PerformanceInterceptor,可以记录和输出执行的 SQL 语句及其执行时间,从而优化慢查询。

9. 插件管理器 (InterceptorChain)

插件管理器负责管理 MyBatis-Plus 中的各种插件,如分页插件、乐观锁插件等。通过 InterceptorChain,可以灵活地添加、配置和管理这些插件。

1.3 MyBatis-Plus工作流程简介

MyBatis-Plus 作为 MyBatis 的增强框架,其工作流程在继承 MyBatis 的基础上进行了优化和扩展。以下是 MyBatis-Plus 的主要工作流程:

1. 配置和初始化

  • 配置文件:开发者可以在配置文件中指定数据库连接信息、Mapper 扫描包等。
  • 自动配置:通过 Spring Boot 的自动配置机制或 XML 配置,MyBatis-Plus 会初始化必要的组件,如 SqlSessionFactory、Mapper 扫描器等。

2. 定义 Mapper 接口

  • 继承 BaseMapper:自定义的 Mapper 接口通常继承自 MyBatis-Plus 提供的 BaseMapper,以获得通用的 CRUD 支持。
  • 注解和接口方法:通过注解或直接在接口中定义方法来声明需要执行的数据库操作。

3. 扫描和注册 Mapper

  • Mapper 扫描器:MyBatis-Plus 会扫描定义的 Mapper 接口,并将它们注册到 Mybatis 的 Mapper 仓库中。
  • 动态代理:MyBatis-Plus 使用动态代理模式为每个 Mapper 接口创建代理对象。

4. SQL 注入器的工作

  • 方法映射:SQL 注入器负责将 Mapper 接口中的方法映射为相应的 SQL 语句。
  • 自定义 SQL:对于注解中定义的 SQL,MyBatis-Plus 会将其注入到对应的 MappedStatement 中。

5. 执行数据库操作

  • 代理对象调用:当调用 Mapper 代理对象的方法时,MyBatis-Plus 会拦截这些调用。
  • SQL 执行:根据方法的签名和注解,MyBatis-Plus 构造 SQL 语句并执行数据库操作。

6. 结果处理

  • 结果映射:执行结果会被 MyBatis-Plus 自动映射到相应的 Java 对象。
  • 分页结果:如果操作是分页查询,MyBatis-Plus 还会处理分页逻辑,返回分页结果。

7. 事务管理

  • 声明式事务:如果应用运行在 Spring 框架中,MyBatis-Plus 可以无缝集成 Spring 的声明式事务管理。
  • 事务传播:支持 Spring 的事务传播行为,简化事务控制。

8. 性能监控与优化

  • SQL 执行监控:MyBatis-Plus 允许开发者监控 SQL 的执行情况,包括执行时间和频率。
  • 执行计划:提供执行计划分析,帮助开发者优化 SQL 语句。

9. 插件扩展

  • 拦截器和插件:MyBatis-Plus 支持通过拦截器和插件来扩展或修改其行为,如分页插件、性能分析插件等。
插件扩展
性能监控与优化
事务管理
结果处理
执行数据库操作
SQL 注入器的工作
扫描和注册 Mapper
定义 Mapper 接口
配置和初始化
插件扩展
拦截器
插件
性能监控与优化
SQL 执行监控
执行计划分析
事务管理
声明式事务
事务传播
结果处理
结果映射
分页结果处理
执行数据库操作
代理对象调用
SQL 执行
SQL 注入器的工作
方法映射
自定义 SQL 注入
扫描和注册 Mapper
Mapper 扫描器
动态代理
定义 Mapper 接口
继承 BaseMapper
注解和接口方法
配置和初始化
Spring Boot 自动配置
XML 配置
开始
结束

工作流程图

第二章:Mapper 对象方法映射为 SQL 语句

在 MyBatis-Plus 中,Mapper 接口方法映射为 SQL 语句的过程是核心功能之一,它允许开发者通过简单的接口方法调用执行复杂的数据库操作。以下是该过程的详细步骤:

2.1 MybatisPlusAutoConfiguration 和 SqlSessionFactory 创建

  1. 自动配置类MybatisPlusAutoConfiguration 是 Spring Boot 的自动配置类,它负责初始化 MyBatis-Plus 的核心组件。
  2. 创建 SqlSessionFactory:通过 sqlSessionFactory() 方法配置 SqlSessionFactory,这是 MyBatis 中用于执行数据库操作的工厂类。

2.2 MybatisXMLConfigBuilder 和 XML 配置文件解析

  1. 配置构建器MybatisXMLConfigBuilder 负责解析 MyBatis 的配置文件和 Mapper XML 文件。
  2. 解析过程:读取 XML 文件中的配置信息,包括数据库连接信息、事务管理器、Mapper 映射等。

2.3 Mapper 接口方法与 SQL 语句的映射过程

  1. 接口方法定义:开发者在 Mapper 接口中定义方法,这些方法代表了要执行的数据库操作。
  2. 注解使用:通过注解(如 @Select, @Update, @Insert, @Delete)直接在接口方法上指定 SQL 语句或查询结果的处理方式。
  3. 动态 SQL:MyBatis-Plus 支持动态 SQL,允许根据条件动态拼接 SQL 语句。

2.4 SQL 语句的动态拼接和 MappedStatement 对象的创建

  1. 动态拼接:SQL 注入器(SqlInjector)根据 Mapper 接口中定义的方法和注解,动态拼接出完整的 SQL 语句。
  2. MappedStatement 对象:每个映射的 SQL 语句都被封装在一个 MappedStatement 对象中,该对象包含了执行 SQL 所需的所有信息,如 SQL 语句本身、参数信息、结果映射等。
  3. 注册到 MyBatis:创建的 MappedStatement 对象被注册到 MyBatis 的配置中,使得在运行时可以通过 Mapper 接口调用对应的 SQL 语句。

2.5 执行 SQL 语句

  1. 代理机制:MyBatis-Plus 使用动态代理机制,当调用 Mapper 接口的方法时,实际上是在调用代理对象的 invoke 方法。
  2. 执行查询或更新:根据 MappedStatement 中的信息,MyBatis-Plus 执行相应的 SQL 查询或更新操作。
  3. 结果处理:查询结果通过 MyBatis 的结果映射机制转换为 Java 对象,返回给开发者。

通过上述步骤,MyBatis-Plus 将 Mapper 接口方法映射为 SQL 语句,并提供了执行数据库操作的能力。这个过程不仅提高了开发效率,还保证了代码的简洁性和可维护性。

第三章:MyBatis-Plus 通用方法的自定义与实现

3.1 自定义通用方法的需求背景

在企业级应用开发中,经常会遇到一些特定的数据库操作需求,这些需求可能无法通过标准的 CRUD 操作来满足。例如,可能需要执行一些特殊的查询,或者在查询时应用特定的业务逻辑。为了应对这些需求,同时保持代码的整洁和可维护性,MyBatis-Plus 提供了自定义通用方法的能力。

3.2 新增 Mapper 方法与 SQL 语句脚本映射枚举

自定义通用方法的第一步是定义一个新的枚举,该枚举扩展了 MyBatis-Plus 的 SqlMethod 枚举。这个枚举将 Mapper 方法名映射到具体的 SQL 语句模板。例如,如果我们想要添加一个从主库查询数据的方法,我们可以定义一个 SqlMethodEx 枚举,如下所示:

public enum SqlMethodEx {
    MASTER_SELECT_LIST("selectListFromMaster", "从主库查询满足条件的多条数据",
            "<bind>" + SqlConstant.DA_MASTER_PARAM + 
            "SELECT ${ew.sqlSelect} FROM ${ew.sqlTable} ${ew.sqlWhere}" + 
            "</bind>");

    private final String method;
    private final String desc;
    private final String sql;

    SqlMethodEx(String method, String desc, String sql) {
        this.method = method;
        this.desc = desc;
        this.sql = sql;
    }

    public String getMethod() {
        return method;
    }

    public String getDesc() {
        return desc;
    }

    public String getSql() {
        return sql;
    }
}

3.3 新增通用方法的定义类和 SQL 注入器

接下来,需要创建一个通用方法的定义类,该类继承自 AbstractMethod。在这个类中,我们将实现如何将自定义的 SQL 语句注入到 MyBatis-Plus 的框架中。例如,我们可以创建一个 SelectListFromMasterMethod 类:

public class SelectListFromMasterMethod extends AbstractMethod {
    @Override
    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
        SqlMethodEx sqlMethod = SqlMethodEx.MASTER_SELECT_LIST;
        // ... 构建 SQL 语句 ...
        SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
        return addSelectMappedStatementForTable(mapperClass, getMethod(sqlMethod), sqlSource, tableInfo);
    }

    private String getMethod(SqlMethodEx sqlMethod) {
        return sqlMethod.getMethod();
    }
}

此外,还需要扩展 SQL 注入器,以识别和处理这些自定义方法。这可以通过继承 DefaultSqlInjector 类并重写 getMethodList 方法来实现:

public class MasterSqlInjector extends DefaultSqlInjector {
    @Override
    public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
        List<AbstractMethod> methods = super.getMethodList(mapperClass);
        methods.add(new SelectListFromMasterMethod());
        return methods;
    }
}

3.4 配置类和基类 Mapper 的扩展

最后,需要在 MyBatis-Plus 的配置类中注册自定义的 SQL 注入器,以确保框架在初始化时能够识别和使用这些注入器。这可以通过创建一个配置类并使用 @Bean 注解来完成:

@Configuration
public class MybatisPlusConfig {
    @Bean
    public MasterSqlInjector masterSqlInjector() {
        return new MasterSqlInjector();
    }
}

同时,我们可以在基类 Mapper 中添加自定义方法,这样任何继承该基类的 Mapper 接口都可以使用这些自定义方法。例如:

public interface MasterMapper<T> extends BaseMapper<T> {
    @Select("<script>${ew.sqlSelect}</script>")
    List<T> selectListFromMaster(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
}

通过这种方式,自定义通用方法就被成功添加到了 MyBatis-Plus 框架中,并且可以在应用程序中按需使用。这种方法大大提升了数据库操作的灵活性和代码的复用性。

第四章:MyBatis-Plus SQL 语句的处理与执行

MyBatis-Plus 中 SQL 语句的处理和执行是一个涉及多个步骤的复杂过程,从 SQL 语句的构建和解析到最终的执行。本章将详细分析这个过程。

4.1 SQL 语句脚本的构建和解析

SQL 语句脚本的构建是 MyBatis-Plus 动态 SQL 功能的核心。通过 SqlScriptUtils 工具类,开发者可以构建复杂的 SQL 语句,这些语句可以根据运行时的条件动态变化。

  • 动态 SQL 模板:MyBatis-Plus 支持使用 XML 或注解中的 OGNL 表达式来构建动态 SQL。例如,可以使用 <if><choose><when><otherwise> 等标签来构建条件语句。
  • 工具类SqlScriptUtils 提供了多种方法来帮助开发者构建 SQL 语句,如 convertIfconvertChoose 等,这些方法可以处理复杂的逻辑并生成相应的 SQL 片段。

4.2 SqlSource 的转化和使用

一旦 SQL 语句脚本构建完成,下一步是将其转化为 SqlSource 对象。SqlSource 是 MyBatis 中用于执行 SQL 的核心对象,它包含了执行 SQL 所需的所有信息。

  • LanguageDriver 接口:MyBatis-Plus 使用 LanguageDriver 接口来将 SQL 脚本转化为 SqlSource。默认实现是 XMLLanguageDriver,它负责解析 XML 中的 SQL 脚本。
  • 创建 SqlSource:通过 LanguageDrivercreateSqlSource 方法,传入配置信息、SQL 脚本和参数类型,最终生成 SqlSource 对象。

4.3 MappedStatement 的创建和缓存

MappedStatement 是 MyBatis 中用于存储与 Mapper 接口方法相关联的 SQL 信息的对象。

  • 关联 SqlSource:将 SqlSource 对象与 Mapper 接口方法关联起来,封装在 MappedStatement 中。
  • 缓存:创建的 MappedStatement 被缓存到 MyBatis 的配置中,这样在 Mapper 接口方法被调用时,可以直接使用缓存中的 MappedStatement 来执行 SQL。

4.4 执行 SQL 语句和参数处理

当 Mapper 接口方法被调用时,MyBatis-Plus 将执行与之关联的 SQL 语句。

  • BoundSql 对象:MyBatis-Plus 使用 BoundSql 对象来处理参数的绑定和替换。它包含了 SQL 语句以及与之相关的参数信息。
  • 参数映射BoundSql 中的参数映射(ParameterMapping)定义了如何从 Mapper 接口方法的参数中提取值,并将其绑定到 SQL 语句的占位符上。
  • 执行流程:MyBatis-Plus 通过 Executor 接口来执行 SQL。在执行前,会通过 BoundSql 来替换 SQL 语句中的占位符,生成最终要执行的 SQL 语句。
  • 结果处理:执行 SQL 后,MyBatis-Plus 会根据 MappedStatement 中定义的结果映射来处理查询结果,将数据库返回的数据映射到 Java 对象。

通过以上步骤,MyBatis-Plus 完成了从 SQL 语句的构建和解析到最终的执行和结果处理的整个流程。这个过程不仅提供了高度的灵活性和动态性,还保证了执行效率和结果的正确性。

第五章:MyBatis-Plus 源码深入分析

5.1 MyBatis-Plus 配置类和 Bean 的创建

在 MyBatis-Plus 的初始化过程中,配置类扮演着核心角色。MybatisPlusAutoConfiguration 是 Spring Boot 的自动配置类,它负责设置 MyBatis-Plus 的基础环境。

  • 自动配置类MybatisPlusAutoConfiguration 根据应用程序的配置自动设置 MyBatis-Plus 的相关 Bean,如 SqlSessionFactoryMapperScannerConfigurer 等。
  • Bean 的创建:自动配置类会创建 GlobalConfigMybatisPlusProperties Bean,这些 Bean 包含了 MyBatis-Plus 的全局配置信息。

5.2 Mapper 接口的扫描和注册

MyBatis-Plus 通过 MapperScannerConfigurer 类来扫描指定包路径下的 Mapper 接口。

  • Mapper 扫描MapperScannerConfigurer 使用 ClassPathMapperScanner 来扫描指定的包路径,查找继承了 Mapper 接口的类。
  • 注册 Bean:扫描到的 Mapper 接口类会被注册为 Spring 的 Bean,这样 Spring 容器就可以管理这些 Mapper 接口的生命周期。

5.3 动态代理和数据库操作的执行流程

MyBatis-Plus 使用动态代理来实现对 Mapper 接口方法的拦截和执行。

  • MapperFactoryBean:每个 Mapper 接口都会创建一个 MapperFactoryBean,它负责创建 Mapper 接口的代理实例。
  • 动态代理:当 Spring 容器需要一个 Mapper 接口的实例时,MapperFactoryBean 会返回一个动态代理对象,该对象实现了 Mapper 接口。
  • 执行流程:当调用 Mapper 接口的代理对象的方法时,会触发 MybatisMapperProxyinvoke 方法,该方法负责构建 SQL 语句并执行数据库操作。

5.4 特殊情况处理:主从数据库路由、读写分离等

MyBatis-Plus 支持处理一些特殊情况,如读写分离和主从数据库路由。

  • 读写分离:通过配置 GlobalConfig 中的 DbConfig,可以设置主从数据库的信息,以及如何进行读写分离。
  • 主从路由:MyBatis-Plus 可以使用自定义的路由策略来决定每个查询应该路由到哪个数据库。这通常是通过实现 IRoute 接口来完成的。
  • 执行策略:在执行 SQL 时,MyBatis-Plus 会根据配置的路由策略和当前的操作类型(读或写)来选择正确的数据库连接。

第六章 参考文献

  1. 谈说1974. (2023). MyBatis-plus 转化处理 SQL 语句的源码分析. CSDN 博客.

  2. Nathan. (2023). MyBatis-plus 自定义通用方法及其实现原理. CSDN 博客.

    • 链接:MyBatis-plus 自定义通用方法及其实现原理
    • 摘要:文章讨论了在 MyBatis-plus 中如何自定义通用方法,包括新增 Mapper 方法与 SQL 语句脚本映射枚举、通用方法的定义类、SQL 注入器,以及如何在配置类中注册自定义 SQL 注入器。
  3. 谈说1974. (2020). MyBatis-plus 源码解析. CSDN 博客.

    • 链接:MyBatis-plus 源码解析
    • 摘要:这篇源码解析文章深入探讨了 MyBatis-plus 的工作原理,包括 Mapper 对象方法如何映射为 SQL 语句、MyBatis-Plus 的自动配置类如何配置 SqlSessionFactory,以及 Mapper 操作数据库的流程。
  4. MyBatis-Plus 官方文档

    • 链接:MyBatis-Plus 官方文档

    • 摘要:官方文档提供了 MyBatis-Plus 的全面指南,包括快速入门、核心功能介绍、配置参考以及最佳实践等。

  5. MyBatis-Plus GitHub 仓库

    • 链接:MyBatis-Plus GitHub 仓库

    • 摘要:GitHub 仓库是 MyBatis-Plus 的源代码存放地,提供了框架的最新代码、issue 跟踪以及 pull request 功能,是贡献者和用户交流的重要平台。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐