`

mybatis源码分析 Exctor的执行代码

 
阅读更多

mybatis执行Sql的核心类是Executor,其结构如图所示,核心是BaseExecutor,继承自BaseExecutor的有BatchExecutor、ClosedExecutor、ReuseExecutor、与SimpleExecutor四个类,分别对应着执行器的四个类型。

在配置文件中可以定义的执行类型如下图所示。

public enum ExecutorType {
  SIMPLE, REUSE, BATCH
}

 
 ExecutorType定义了的三种Executor类型。

同时,继承子Executor的类有CachingExecutor,该执行器实现了mybatis缓存。但是具体的sql执行等仍然是委托给上面提到的三个(Closed未用)执行器。

 

以SqlSession的SelectList举例了解执行过程。

首先执行位于DefaultSqlSession的selectList

  @Override
  public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
    try {
      MappedStatement ms = configuration.getMappedStatement(statement);
      return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
    } catch (Exception e) {
      throw ExceptionFactory.wrapException("Error querying database.  Cause: " + e, e);
    } finally {
      ErrorContext.instance().reset();
    }
  }

 该executor为cachingExecutor,该执行器将具体的执行功能委托给BaseExecutor的基类去完成,具体的用哪个Executor,还需要用户在配置文件中定义,首先从Configuration实例中获取mybatis映射语句,然后调用CachingExecutor执行query

 

  @Override
  public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
    BoundSql boundSql = ms.getBoundSql(parameterObject); //生成sql
    CacheKey key = createCacheKey(ms, parameterObject, rowBounds, boundSql); //缓存键值
    return query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);  //进一步处理
  }

 mybatis支持缓存,根据sql,参数等信息首先查询缓存,若没有命中的话才会执行数据库查询,接着:

  @Override
  public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql)
      throws SQLException {
    Cache cache = ms.getCache();
    if (cache != null) {   //如果定义缓存,则从缓存中fetch
      flushCacheIfRequired(ms);
      if (ms.isUseCache() && resultHandler == null) {
        ensureNoOutParams(ms, parameterObject, boundSql);
        @SuppressWarnings("unchecked")
        List<E> list = (List<E>) tcm.getObject(cache, key);
        if (list == null) {
          list = delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql); //缓存没有,继续查数据库并更新缓存
          tcm.putObject(cache, key, list); // issue #578 and #116
        }
        return list;
      }
    }
    return delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql); //若没有定义缓存,则直接查询数据库
  }

 delegate.<E> query(***);语句将数据库查询委托给BaseExecutor的具体实现,也就是BATCH、SIMPLE、REUSE中的任何一个(在配置文件中指定)。这里以Simple,无缓存为例(最简单)。紧接着或调用BaseExecutor中的query方法。

BaseExecutor.java
 @Override
  public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
    BoundSql boundSql = ms.getBoundSql(parameter);
    CacheKey key = createCacheKey(ms, parameter, rowBounds, boundSql); //生成缓存主键
    return query(ms, parameter, rowBounds, resultHandler, key, boundSql); //调用含有缓存功能的query方法
 }

 最终会执行BaseExecutor的doQuery方法。该方法,该方法是工厂方法,在具体的类中有着不同的实现。在SimpleExecutor中的实现如下所示:

  @Override
  public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
    Statement stmt = null;
    try {
      Configuration configuration = ms.getConfiguration();
      StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
      stmt = prepareStatement(handler, ms.getStatementLog());
      return handler.<E>query(stmt, resultHandler);
    } finally {
      closeStatement(stmt);
    }
  }

 stmt是javasql中的类,感觉和执行sql更接近了。 是StatementHandler负责生成最终要执行的sql代码的类。configuration.newStatementHandler()方法用来生成StatementHandler。

  public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
    StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql);
    statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler);
    return statementHandler;
  }

 生成的是RoutingStatementHandler,也是一个委托模式吧,图中是其继承层次关系。

 
RoutingStatementHandler把具体的实现委托给BaseStatementHandler的基类完成。interceptorChain.pluginAll(statementHandler)用于mybatis的插件功能,用所有的插件对此接口生成代理,以便对statementHandler接口的所有方法进行拦截(具体内容见职责链模式与动态代理模式)。

 

至此,Executor的所有工具已经完成剩下的是StatementHandler的职责。

 

 

  • 大小: 23.7 KB
  • 大小: 23.4 KB
分享到:
评论

相关推荐

    mybatis源码分析视频

    本资源“mybatis源码分析视频”是针对MyBatis框架进行深入剖析的教程,通过视频和文档的形式帮助学习者理解其内部工作机制。 1. **MyBatis简介** MyBatis消除了几乎所有的JDBC代码和手动设置参数以及获取结果集。...

    MyBatis源码分析.pdf

    MyBatis源码分析 MyBatis是一款流行的Java持久层框架,提供了强大的数据库访问能力,本文将对MyBatis的源码进行深入分析,从而帮助读者更好地理解MyBatis的工作机理。 1. MyBatis入门 MyBatis是一款基于Java的...

    Mybatis源码分析.pdf

    总结起来,MyBatis源码分析涵盖了从配置加载到数据库操作的全过程,涉及到了配置解析、SQL执行、结果映射等多个关键环节,以及Executor、StatementHandler等核心组件。通过深入学习MyBatis的源码,开发者不仅可以...

    mybatis源码分析思维导图.rar

    MyBatis的源码分析对于理解其工作原理、优化数据库交互以及进行二次开发至关重要。通过思维导图的方式,我们可以更直观、系统地理解MyBatis的架构和流程。 首先,MyBatis的核心概念包括SqlSessionFactory、...

    mybatis源码分析

    通过对MyBatis源码的分析,开发者可以更深入地理解其内部运作机制,从而更好地优化应用,解决实际问题。同时,这也是一种提升个人技术水平和解决问题能力的有效途径。在阅读源码过程中,可能会遇到各种设计模式和...

    Mybatis源码学习-代码+笔记

    Mybatis 是一款流行的Java持久层框架,它简化了数据库操作,通过XML或注解的方式将SQL语句与Java代码绑定,使得开发更为简洁高效。在深入学习Mybatis源码的过程中,我们可以了解到它的工作原理,更好地优化数据库...

    Mybatis学习源码的实例代码

    在这个"Mybatis学习源码的实例代码"中,我们可以深入理解Mybatis的工作机制和内部实现。 首先,让我们从基础开始。Mybatis的主要组件包括SqlSessionFactory、SqlSession和Mapper接口。SqlSessionFactory是Mybatis的...

    MyBatis源码详解学习.zip

    源码分析时,会了解到SqlSessionFactoryBuilder、SqlSessionFactory、SqlSession等关键类的作用,它们构成了MyBatis的主要工作流程。 SqlSessionFactoryBuilder用于构建SqlSessionFactory,这是MyBatis的核心工厂,...

    Spring整合Mybatis源码解析

    Spring整合Mybatis源码解析

    《MyBatis 基础笔记》源代码

    MyBatis 是一款著名的Java持久层框架,它简化了数据库操作与Java对象之间的映射,提供了灵活的SQL构建和执行机制。本笔记源代码涵盖了MyBatis的基本使用、配置、映射器接口、XML配置文件、注解方式的映射以及动态SQL...

    mybatis-plus最新代码生成器项目源码 :mybatis-plus-generator.zip

    mybatis-plus最新代码生成器项目源码 :mybatis-plus-generator.zip mybatis-plus最新代码生成器项目源码 :mybatis-plus-generator.zip mybatis-plus最新代码生成器项目源码 :mybatis-plus-generator.zip ...

    MyBatis 源码解析:通过源码深入理解 SQL 的执行过程 - GitChat

    MyBatis 源码解析:通过源码深入理解 SQL 的执行过程 抓下来打包成了HTML文件, 方便离线观看

    阿里巴巴P7架构师纯手工打造MyBatis源码——1小时解密底层源码.txt

    ### MyBatis源码解析——由阿里巴巴P7架构师纯手工打造 #### 一、前言 在现代软件开发过程中,持久层框架如MyBatis因其简单易用、灵活高效的特点而受到广泛欢迎。作为一款优秀的Java持久层框架,MyBatis通过SQL...

    5套完整springboot+mybatis源码下载只供学习之用.rar

    通过学习这些源码,你可以深入理解SpringBoot如何启动、如何配置自动装配,以及MyBatis如何与数据库交互。同时,Shiro的使用也能帮助你掌握用户权限的控制。对于初学者,这是一个很好的实践平台,对于有经验的开发者...

    MyBatis源码包

    描述中提到的"Eclipse中点击Open Source导入源码",意味着我们可以使用Eclipse这样的集成开发环境(IDE)来查看和分析MyBatis的源代码。Eclipse提供了强大的代码浏览和调试功能,使得开发者在研究源码时更加便捷。 ...

    一本小小的MyBatis源码分析书.rar

    《一本小小的MyBatis源码分析书》是针对Java开发者,特别是初中级开发工程师的一份重要参考资料,专注于解析MyBatis这一流行持久层框架的源代码。MyBatis作为一个轻量级的ORM(对象关系映射)框架,它极大地简化了...

    mybatis源码.rar

    源码分析是理解框架工作原理的重要途径,通过阅读MyBatis的源码,我们可以深入学习其内部机制,包括SQL动态生成、结果映射、事务管理等方面。 1. SQL动态生成:MyBatis的核心之一是SQL动态语句。在XML配置文件或...

    mybatis源码jar包

    在深入探讨MyBatis源码之前,我们首先需要理解MyBatis的基本概念和功能。MyBatis消除了几乎所有的JDBC代码和手动设置参数以及获取结果集。MyBatis可以使用简单的XML或注解进行配置和原始映射,将接口和Java的POJOs...

Global site tag (gtag.js) - Google Analytics