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的职责。
相关推荐
本资源“mybatis源码分析视频”是针对MyBatis框架进行深入剖析的教程,通过视频和文档的形式帮助学习者理解其内部工作机制。 1. **MyBatis简介** MyBatis消除了几乎所有的JDBC代码和手动设置参数以及获取结果集。...
MyBatis源码分析 MyBatis是一款流行的Java持久层框架,提供了强大的数据库访问能力,本文将对MyBatis的源码进行深入分析,从而帮助读者更好地理解MyBatis的工作机理。 1. MyBatis入门 MyBatis是一款基于Java的...
总结起来,MyBatis源码分析涵盖了从配置加载到数据库操作的全过程,涉及到了配置解析、SQL执行、结果映射等多个关键环节,以及Executor、StatementHandler等核心组件。通过深入学习MyBatis的源码,开发者不仅可以...
MyBatis的源码分析对于理解其工作原理、优化数据库交互以及进行二次开发至关重要。通过思维导图的方式,我们可以更直观、系统地理解MyBatis的架构和流程。 首先,MyBatis的核心概念包括SqlSessionFactory、...
通过对MyBatis源码的分析,开发者可以更深入地理解其内部运作机制,从而更好地优化应用,解决实际问题。同时,这也是一种提升个人技术水平和解决问题能力的有效途径。在阅读源码过程中,可能会遇到各种设计模式和...
Mybatis 是一款流行的Java持久层框架,它简化了数据库操作,通过XML或注解的方式将SQL语句与Java代码绑定,使得开发更为简洁高效。在深入学习Mybatis源码的过程中,我们可以了解到它的工作原理,更好地优化数据库...
在这个"Mybatis学习源码的实例代码"中,我们可以深入理解Mybatis的工作机制和内部实现。 首先,让我们从基础开始。Mybatis的主要组件包括SqlSessionFactory、SqlSession和Mapper接口。SqlSessionFactory是Mybatis的...
源码分析时,会了解到SqlSessionFactoryBuilder、SqlSessionFactory、SqlSession等关键类的作用,它们构成了MyBatis的主要工作流程。 SqlSessionFactoryBuilder用于构建SqlSessionFactory,这是MyBatis的核心工厂,...
Spring整合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 源码解析:通过源码深入理解 SQL 的执行过程 抓下来打包成了HTML文件, 方便离线观看
### MyBatis源码解析——由阿里巴巴P7架构师纯手工打造 #### 一、前言 在现代软件开发过程中,持久层框架如MyBatis因其简单易用、灵活高效的特点而受到广泛欢迎。作为一款优秀的Java持久层框架,MyBatis通过SQL...
通过学习这些源码,你可以深入理解SpringBoot如何启动、如何配置自动装配,以及MyBatis如何与数据库交互。同时,Shiro的使用也能帮助你掌握用户权限的控制。对于初学者,这是一个很好的实践平台,对于有经验的开发者...
描述中提到的"Eclipse中点击Open Source导入源码",意味着我们可以使用Eclipse这样的集成开发环境(IDE)来查看和分析MyBatis的源代码。Eclipse提供了强大的代码浏览和调试功能,使得开发者在研究源码时更加便捷。 ...
《一本小小的MyBatis源码分析书》是针对Java开发者,特别是初中级开发工程师的一份重要参考资料,专注于解析MyBatis这一流行持久层框架的源代码。MyBatis作为一个轻量级的ORM(对象关系映射)框架,它极大地简化了...
源码分析是理解框架工作原理的重要途径,通过阅读MyBatis的源码,我们可以深入学习其内部机制,包括SQL动态生成、结果映射、事务管理等方面。 1. SQL动态生成:MyBatis的核心之一是SQL动态语句。在XML配置文件或...
在深入探讨MyBatis源码之前,我们首先需要理解MyBatis的基本概念和功能。MyBatis消除了几乎所有的JDBC代码和手动设置参数以及获取结果集。MyBatis可以使用简单的XML或注解进行配置和原始映射,将接口和Java的POJOs...