欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

MyBatis源码-深入理解MyBatis Executor的设计思想

发布时间:2025/3/21 编程问答 41 豆豆
生活随笔 收集整理的这篇文章主要介绍了 MyBatis源码-深入理解MyBatis Executor的设计思想 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

文章目录

  • Pre
  • JDBC的执行过程
    • JDBC Demo
    • JDBC Statement 接口
  • MyBatis执行过程
    • 四大组件
    • 组件之间的关系
  • Executor 执行器组件
    • 架构总览
    • 接口继承关系

Pre

如果MyBatis的基础用法还不熟悉,31篇入门博客拿走不谢

戳戳戳 —> https://blog.csdn.net/yangshangwei/category_7205317.html


JDBC的执行过程

MyBatis 半自动的ORM框架 ,归根到底底层还是用的JDBC来访问数据库 , 所以有必要先回顾一下JDBC的执行过程

JDBC Demo

【演示Table 】


【演示Code】

public class JdbcTest {public static final String URL = "jdbc:mysql://127.0.0.1:3306/o2o?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8&useSSL=false";public static final String USERNAME = "root";public static final String PASSWORD = "root";private Connection connection;@Beforepublic void init() throws SQLException {// 第一步 获取连接connection = DriverManager.getConnection(URL, USERNAME, PASSWORD);}@Afterpublic void over() throws SQLException {connection.close();}@Testpublic void jdbcTest() throws SQLException {// 第二步 预编译 & 设置参数 String sql = "SELECT * FROM tb_area WHERE `area_name`=?";PreparedStatement sql1 = connection.prepareStatement(sql);sql1.setString(1,"北京");// 第三步 执行SQLsql1.execute();// 第四步 获取返回结果ResultSet resultSet = sql1.getResultSet();while (resultSet.next()) {System.out.println(resultSet.getString(3));}resultSet.close();sql1.close();;}}

【执行结果】


【JDBC执行步骤总结】

无非就是下面几步

  • 获取连接
  • 预处理SQL ,设置参数等
  • 执行SQL
  • 获取返回结果
  • Mybatis既然是JDBC的封装框架, 那自然要处理 预处理这一步 ,所以有必要了解下JDBC中的Statement 接口


    JDBC Statement 接口

    整体接口和类的关系图如下

    这里重点说一下 Statement 接口 ,通过该组件来发送对应的SQL与参数 .

    它有三种类型:分别是 Statement,PreparedStatement和CallableStatement 接口, 继承关系如上,

    【Statement接口】

    • 普通的不带参的查询SQL
    • 支持批量更新,批量删除

    【PreparedStatement接口】

    • 继承自Statement接口
    • 可变参数的SQL,编译一次,执行多次,效率高
    • 安全,有效防止Sql注入等问题
    • 支持批量更新,批量删除

    【CallableStatement接口】

    • 继承自PreparedStatement接口
    • 支持带参数的SQL操作
    • 支持调用存储过程,提供了对输出和输入/输出参数(INOUT)的支持


    除了常见的接口方法, Statement 中还有2个非常规方法需要关注下,因为后续在MyBatis中源码会有体现。

    • addBatch: 批处理操作,将多个SQL合并在一起,最后调用executeBatch 一起发送至数据库执行

    • setFetchSize:设置从数据库每次读取的数量单位。该举措是为了防止一次性从数据库加载数据过多,导致内存溢出。(MySQL不支持 ,Oracle支持)


    MyBatis执行过程

    推荐使用鲁班大叔的源码地图来梳理MyBatis的源码执行过程,更直观易懂 。 ------->戳这里<----------

    四大组件

    每个组件的作用如下:

    • 接口代理: 简化对MyBatis使用,底层使用动态代理实现

    • Sql会话: 提供增删改查API, 本身不做业务逻辑的处理,所有处理都会交给执行器Executor。这是一个典型的门面设计模式

    • 执行器: 核心作用是处理SQL请求、事务管理、维护缓存以及批处理等 。执行器在的角色更像是一个管理员,接收SQL请求,然后根据缓存、批处理等逻辑来决定如何执行这个SQL请求,并交给JDBC处理器执行具体SQL

    • JDBC处理器: 主要具体处理JDBCSQL和参数 。在会话中每调用一次CRUD,JDBC处理器就会生成一个实例与之对应(命中缓存除外)

    StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);

    请注意在一次SQL会话过程当中四个组件的实例比值分别是 1:1:1:n


    组件之间的关系

    一个SQL请求通过会话到达执行器,然后交给对应的JDBC处理器进行处理。

    另外所有的组件都不是线程安全的,不能跨线程使用 (currentSql 全局变量 ,线程不安全 )

    接下来我们重点看下Executor组件,从源码上剖析该组件的设计思想。


    Executor 执行器组件

    架构总览

    Executor是MyBatis执行者接口 ,执行器的主要功能包括:

    • 基本功能:改、查,(增删—>也是改)

    • 缓存维护:这里的缓存主要是为一级缓存服务,功能包括创建缓存Key、清理缓存、判断缓存是否存在

    • 事务管理:提交、回滚、关闭、批处理刷新


    接口继承关系

    后面我们重点看下Executor的 三个实现子类。

    分别是:SimpleExecutor(简单执行器)、ReuseExecutor(重用执行器)、BatchExecutor(批处理执行器)。

    MyBatis源码-深入解读Executor的三个实现类


    总结

    以上是生活随笔为你收集整理的MyBatis源码-深入理解MyBatis Executor的设计思想的全部内容,希望文章能够帮你解决所遇到的问题。

    如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。