MyBatis源码-解读Executor的三个实现类之ReuseExecutor(重用执行器)

举报
小工匠 发表于 2021/09/11 00:14:22 2021/09/11
2.2k+ 0 0
【摘要】 文章目录 PreExecutor 执行器接口继承关系ReuseExecutor(重用执行器)入门小demo源码实现 Pre MyBatis源码-深入理解MyBatis Execut...

在这里插入图片描述

Pre

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

工程部分见
MyBatis源码- SqlSession门面模式 & selectList 源码解析

在这里插入图片描述

实际中,我们都是面向SqlSession编程的,不会直接调用Executor来执行业务逻辑,这里我们仅仅是为了深入了解下Executor体系架构才这么搞的,切记。


Executor 执行器

在这里插入图片描述


接口继承关系

在这里插入图片描述

这里我们重点看下Executor的 三个实现子类。

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


ReuseExecutor(重用执行器)

回归下JDBC中的 Statement , 再和MyBatis 所封装的 对比一下

在这里插入图片描述

PreparedStatement 支持预编译参数

在这里插入图片描述

MyBatis的ReuseExecutor就是利用了JDBC Statement的这个特点 来处理的。

入门小demo


    @Test
    public void testReuseExecutor() throws SQLException {
        // 通过factory.openSession().getConnection()实例化JdbcTransaction ,用于构建ReuseExecutor
        jdbcTransaction = new JdbcTransaction(factory.openSession().getConnection());
        // 映射SQL
        ms = configuration.getMappedStatement("com.artisan.UserMapper.selectByid");

        // 实例化ReuseExecutor
        ReuseExecutor executor = new ReuseExecutor(configuration, jdbcTransaction);
        // 调用doQuery执行查询
        List<User> userList = executor.doQuery(ms, 1, RowBounds.DEFAULT, Executor.NO_RESULT_HANDLER, ms.getBoundSql(1));
        System.out.println(userList.get(0));
        List<User> userList2 = executor.doQuery(ms, 1, RowBounds.DEFAULT, Executor.NO_RESULT_HANDLER, ms.getBoundSql(1));
        System.out.println(userList2.get(0));

    }

  
 

执行结果

在这里插入图片描述
可以看到 相同的SQL语句 会缓存对应的PrepareStatement , 缓存的生命周期: 会话有效期


源码实现

在这里插入图片描述

Key 是 sql , Value 是 Statement

执行过程:

executor.doQuery ----> prepareStatement(handler, ms.getStatementLog())

---------> 见下方源码

  private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
    Statement stmt;
    BoundSql boundSql = handler.getBoundSql();
    String sql = boundSql.getSql();
    if (hasStatementFor(sql)) {
      stmt = getStatement(sql);
      applyTransactionTimeout(stmt);
    } else {
      Connection connection = getConnection(statementLog);
      stmt = handler.prepare(connection, transaction.getTimeout());
      putStatement(sql, stmt);
    }
    handler.parameterize(stmt);
    return stmt;
  }

  
 

先判断本地缓存statementMap是否有数据,有的话从statementMap获取,没有的话建立Statement,并存入本地缓存statementMap 。

注意这个缓存的声明周期 是仅限于本次会话。 会话结束后,这些缓存都会被销毁掉。

区别于SimpleExecutor的实现,多了个本地缓存。 推荐使用ReuseExecutor 。


文章来源: artisan.blog.csdn.net,作者:小小工匠,版权归原作者所有,如需转载,请联系作者。

原文链接:artisan.blog.csdn.net/article/details/106749316

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

作者其他文章

评论(0

抱歉,系统识别当前为高风险访问,暂不支持该操作

    全部回复

    上滑加载中

    设置昵称

    在此一键设置昵称,即可参与社区互动!

    *长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

    *长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。