• Mybatis介绍


    MyBatis 介绍

    Apache 基金会中的 iBatis 项目是 MyBatis 的前身。iBatis 项目由于各种原因,在 Apache 基金会并没有得到很好的发展,最终于 2010 年脱离 Apache,并更名为 MyBatis。三年后,也就是 2013 年,MyBatis 将源代码迁移到了 GitHub。

    MyBatis 中一个重要的功能就是可以帮助 Java 开发封装重复性的 JDBC 代码,这与前文分析的 Spring Data JPA 、Hibernate 等 ORM 框架一样。MyBatis 封装重复性代码的方式是通过 Mapper 映射配置文件以及相关注解,将 ResultSet 结果映射为 Java 对象,在具体的映射规则中可以嵌套其他映射规则和必要的子查询,这样就可以轻松实现复杂映射的逻辑,当然,也能够实现一对一、一对多、多对多关系映射以及相应的双向关系映射。

    很多人会将 Hibernate 和 MyBatis 做比较,认为 Hibernate 是全自动 ORM 框架,而 MyBatis 只是半自动的 ORM 框架或是一个 SQL 模板引擎。其实,这些比较都无法完全说明一个框架比另一个框架先进,关键还是看应用场景。

    MyBatis 相较于 Hibernate 和各类 JPA 实现框架更加灵活、更加轻量级、更加可控。

    • 我们可以在 MyBatis 的 Mapper 映射文件中,直接编写原生的 SQL 语句,应用底层数据库产品的方言,这就给了我们直接优化 SQL 语句的机会;

    • 我们还可以按照数据库的使用规则,让原生 SQL 语句选择我们期望的索引,从而保证服务的性能,这就特别适合大数据量、高并发等需要将 SQL 优化到极致的场景;

    • 在编写原生 SQL 语句时,我们也能够更加方便地控制结果集中的列,而不是查询所有列并映射对象后返回,这在列比较多的时候也能起到一定的优化效果。(当然,Hibernate 也能实现这种效果,需要在实体类添加对应的构造方法。)

    在实际业务中,对同一数据集的查询条件可能是动态变化的,如果你有使用 JDBC 或其他类似框架的经历应该能体会到,拼接 SQL 语句字符串是一件非常麻烦的事情,尤其是条件复杂的场景中,拼接过程要特别小心,要确保在合适的位置添加“where”“and”“in”等 SQL 语句的关键字以及空格、逗号、等号等分隔符,而且这个拼接过程非常枯燥、没有技术含量,可能经过反复调试才能得到一个可执行的 SQL 语句。

    MyBatis 提供了强大的动态 SQL 功能来帮助我们开发者摆脱这种重复劳动,我们只需要在映射配置文件中编写好动态 SQL 语句,MyBatis 就可以根据执行时传入的实际参数值拼凑出完整的、可执行的 SQL 语句。

    总结

    • 从性能角度来看,Hibernate、Spring Data JPA 在对 SQL 语句的掌控、SQL 手工调优、多表连接查询等方面,不及 MyBatis 直接使用原生 SQL 语句方便、高效;

    • 从可移植性角度来看,Hibernate 帮助我们屏蔽了底层数据库方言,Spring Data JPA 帮我们屏蔽了 ORM 的差异,而 MyBatis 因为直接编写原生 SQL,会与具体的数据库完全绑定(但实践中很少有项目会来回切换底层使用的数据库产品或 ORM 框架,所以这点并不是特别重要);

    • 从开发效率角度来看,Hibernate、Spring Data JPA 处理中小型项目的效率会略高于 MyBatis(这主要还是看需求和开发者技术栈)。

    Mybatis 优点

    MyBatis 是 Java 生态中非常著名的一款 ORM 框架,这是一款很值得你学习和研究的 Java 持久化框架。原因主要有两个:

    第一,MyBatis 本身就是一款设计非常精良、架构设计非常清晰的持久层框架,并且 MyBatis 中还使用到了很多经典的设计模式,例如,工厂方法模式、适配器模式、装饰器模式、代理模式等。 在阅读 MyBatis 代码的时候,你也许会惊奇地发现:原来大师设计出来的代码真的是一种艺术。所以,从这个层面来讲,深入研究 MyBatis 原理,甚至阅读它的源码,不仅可以帮助你快速解决工作中遇到的 MyBatis 相关问题,还可以提高你的设计思维。

    第二,MyBatis 提供了很多扩展点,例如,MyBatis 的插件机制、对第三方日志框架和第三方数据源的兼容等。 正由于这种可扩展的能力,让 MyBatis 的生命力非常旺盛,这也是很多 Java 开发人员将 MyBatis 作为自己首选 Java 持久化框架的原因之一,反过来促进了 MyBatis 用户的不断壮大。

    第三,开发人员使用 MyBatis 上手会非常快,具有很强的易用性和可靠性。这也是 MyBatis 流行的一个很重要的原因。当你具备了 MySQL 和 JDBC 的基础知识之后,学习 MyBatis 的难度远远小于 Hibernate 等持久化框架。

    MyBatis 架构简介

    MyBatis 分为三层架构,分别是基础支撑层、核心处理层和接口层,如下图所示:

    image-20210201164800497

    基础支撑层

    基础支撑层是整个 MyBatis 框架的地基,为整个 MyBatis 框架提供了非常基础的功能,其中每个模块都提供了一个内聚的、单一的能力,MyBatis 基础支撑层按照这些单一的能力可以划分为上图所示的九个基础模块。

    由于资源加载模块的功能非常简单,使用频率也不高,这里我就不介绍了,你若感兴趣可以自行查阅相关资料去了解和学习。下面我就来简单描述这剩下的八个模块的基本功能,在本课程第二个模块,我还会带你详细分析这些基础模块的具体实现。

    第一个,类型转换模块。 在上一讲展示的订单系统实现中,我们可以在 mybatis-config.xml 配置文件中通过 标签为一个类定义一个别名,这里用到的“别名机制”就是由 MyBatis 基础支撑层中的类型转换模块实现的。

    除了“别名机制”,类型转换模块还实现了 MyBatis 中 JDBC 类型与 Java 类型之间的相互转换,这一功能在绑定实参、映射 ResultSet 场景中都有所体现:

    在 SQL 模板绑定用户传入实参的场景中,类型转换模块会将 Java 类型数据转换成 JDBC 类型数据;

    在将 ResultSet 映射成结果对象的时候,类型转换模块会将 JDBC 类型数据转换成 Java 类型数据。

    具体情况如下图所示:

    image-20210201164842421

    第二个,日志模块。 日志是我们生产实践中排查问题、定位 Bug、锁定性能瓶颈的主要线索来源,在任何一个成熟系统中都会有级别合理、信息翔实的日志模块,MyBatis 也不例外。MyBatis 提供了日志模块来集成 Java 生态中的第三方日志框架,该模块目前可以集成 Log4j、Log4j2、slf4j 等优秀的日志框架。

    第三个,反射工具模块。 Java 中的反射功能非常强大,许多开源框架都会依赖反射实现一些相对灵活的需求,但是大多数 Java 程序员在实际工作中很少会直接使用到反射技术。MyBatis 的反射工具箱是在 Java 反射的基础之上进行的一层封装,为上层使用方提供更加灵活、方便的 API 接口,同时缓存 Java 的原生反射相关的元数据,提升了反射代码执行的效率,优化了反射操作的性能。

    第四个,Binding 模块。 在上一讲介绍的订单系统示例中,我们可以通过 SqlSession 获取 Mapper 接口的代理,然后通过这个代理执行关联 Mapper.xml 文件中的数据库操作。通过这种方式,可以将一些错误提前到编译期,该功能就是通过 Binding 模块完成的。

    第五个,数据源模块。 持久层框架核心组件之一就是数据源,一款性能出众的数据源可以成倍提升系统的性能。MyBatis 自身提供了一套不错的数据源实现,也是 MyBatis 的默认实现。另外,在 Java 生态中,就有很多优异开源的数据源可供选择,MyBatis 的数据源模块中也提供了与第三方数据源集成的相关接口,这也为用户提供了更多的选择空间,提升了数据源切换的灵活性。

    第六个,缓存模块。 数据库是实践生成中非常核心的存储,很多业务数据都会落地到数据库,所以数据库性能的优劣直接影响了上层业务系统的优劣。我们很多线上业务都是读多写少的场景,在数据库遇到瓶颈时,缓存是最有效、最常用的手段之一(如下图所示),正确使用缓存可以将一部分数据库请求拦截在缓存这一层,这就能够减少一部分数据库的压力,提高系统性能。

    image-20210201164903140

    除了使用 Redis、Memcached 等外置的第三方缓存以外,持久化框架一般也会自带内置的缓存,例如,MyBatis 就提供了一级缓存和二级缓存,具体实现位于基础支撑层的缓存模块中。

    第七个,解析器模块。 MyBatis 中有两大部分配置文件需要解析,一个是 mybatis-config.xml 配置文件,另一个是 Mapper.xml 配置文件。这两个文件都是由 MyBatis 的解析器模块进行解析的,其中主要是依赖 XPath 实现 XML 配置文件以及各类表达式的高效解析。

    第八个,事务管理模块。 持久层框架一般都会提供一套事务管理机制实现数据库的事务控制,MyBatis 对数据库中的事务进行了一层简单的抽象,提供了简单易用的事务接口和实现。一般情况下,Java 项目都会集成 Spring,并由 Spring 框架管理事务。在后面的课程中,我还会深入讲解 MyBatis 与 Spring 集成的原理,其中就包括事务管理相关的集成。

    核心处理层

    核心处理层是 MyBatis 核心实现所在,其中涉及 MyBatis 的初始化以及执行一条 SQL 语句的全流程。

    第一个,配置解析。 我们知道,MyBatis 有三处可以添加配置信息的地方,分别是:mybatis-config.xml 配置文件、Mapper.xml 配置文件以及 Mapper 接口中的注解信息。在 MyBatis 初始化过程中,会加载这些配置信息,并将解析之后得到的配置对象保存到 Configuration 对象中。

    例如,在订单系统示例中使用的 标签(也就是自定义的查询结果集映射规则)会被解析成 ResultMap 对象。我们可以利用得到的 Configuration 对象创建 SqlSessionFactory 对象(也就是创建 SqlSession 对象的工厂对象),之后即可创建 SqlSession 对象执行数据库操作了。

    第二个,SQL 解析与 scripting 模块。 MyBatis 的最大亮点应该要数其动态 SQL 功能了,只需要通过 MyBatis 提供的标签即可根据实际的运行条件动态生成实际执行的 SQL 语句。MyBatis 提供的动态 SQL 标签非常丰富,包括 标签、 标签、 标签、 标签等。

    MyBatis 中的 scripting 模块就是负责动态生成 SQL 的核心模块。它会根据运行时用户传入的实参,解析动态 SQL 中的标签,并形成 SQL 模板,然后处理 SQL 模板中的占位符,用运行时的实参填充占位符,得到数据库真正可执行的 SQL 语句。

    第三个,SQL 执行。 在 MyBatis 中,要执行一条 SQL 语句,会涉及非常多的组件,比较核心的有:Executor、StatementHandler、ParameterHandler 和 ResultSetHandler。

    其中,Executor 会调用事务管理模块实现事务的相关控制,同时会通过缓存模块管理一级缓存和二级缓存。SQL 语句的真正执行将会由 StatementHandler 实现。那具体是怎么完成的呢?StatementHandler 会先依赖 ParameterHandler 进行 SQL 模板的实参绑定,然后由 java.sql.Statement 对象将 SQL 语句以及绑定好的实参传到数据库执行,从数据库中拿到 ResultSet,最后,由 ResultSetHandler 将 ResultSet 映射成 Java 对象返回给调用方,这就是 SQL 执行模块的核心。

    下图展示了 MyBatis 执行一条 SQL 语句的核心过程:

    image-20210201164937461

    第四个,插件。 很多成熟的开源框架,都会以各种方式提供扩展能力。当框架原生能力不能满足某些场景的时候,就可以针对这些场景实现一些插件来满足需求,这样的框架才能有足够的生命力。这也是 MyBatis 插件接口存在的意义。

    与此同时,在实际应用的时候,你也可以通过自定义插件来扩展 MyBatis,或者改变 MyBatis 的默认行为。因为插件会影响 MyBatis 内核的行为,所以在自定义插件之前,你必须非常了解 MyBatis 内部的运行原理,以避免写出不符合预期的插件,引入一些诡异的功能 Bug 或性能问题。

    接口层

    接口层是 MyBatis 暴露给调用的接口集合,这些接口都是使用 MyBatis 时最常用的一些接口,例如,SqlSession 接口、SqlSessionFactory 接口等。其中,最核心的是 SqlSession 接口,你可以通过它实现很多功能,例如,获取 Mapper 代理、执行 SQL 语句、控制事务开关等。

  • 相关阅读:
    10年后我又来看看我自己!
    KubernetesKuboard
    VSCode SSH 免密登录
    Windows Terminal 使用 PuTTY 连接 COM 串口
    PuTTY SSH 免密登录
    FastDDS 安装过程的坑🕳坑🕳坑🕳坑🕳坑🕳坑🕳
    Samba 安装、配置、共享 home 目录、创建用户、设置密码、映射盘符
    Win10 恢复快捷方式小箭头
    CSAPP 并发编程读书笔记
    修改 VSCode 终端配色
  • 原文地址:https://www.cnblogs.com/dalianpai/p/14357667.html
Copyright © 2020-2023  润新知