通过上一篇文章的分析我们,我初步了解了它是如何创建sessionFactory的(地址:Mybatis源码分析之SqlSessionFactory(一)),

今天我们分析下Mybatis如何创建SqlSession( sessionFactory.openSession())和Excutor到底做了什么事情

还是上篇的代码demo

  1.   public static void main(String[] args) throws Exception {
  2.         SqlSessionFactory sessionFactory = null;
  3.         String resource = "configuration.xml";
  4.         sessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsReader(resource));
  5.         SqlSession sqlSession = sessionFactory.openSession();
  6.         UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
  7.         System.out.println(userMapper.findUserById(1));
  8.   }

1:openSessionFromDataSource

通过openSession()最终调用的是 openSessionFromDataSource,源码如下:

  1.   private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
  2.     Transaction tx = null;
  3.     try {
  4.       final Environment environment = configuration.getEnvironment();
  5.       final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
  6.       tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
  7.       final Executor executor = configuration.newExecutor(tx, execType);
  8.       return new DefaultSqlSession(configuration, executor, autoCommit);
  9.     } catch (Exception e) {
  10.       closeTransaction(tx); // may have fetched a connection so lets call close()
  11.       throw ExceptionFactory.wrapException("Error opening session.  Cause: " + e, e);
  12.     } finally {
  13.       ErrorContext.instance().reset();
  14.     }
  15.   }

说明:ExecutorType(执行器类型)类型有 SIMPLE(默认),REUSE,BATCH,

TransactionIsolationLevel  隔离级别5种

NONE(Connection.TRANSACTION_NONE),

READ_COMMITTED(Connection.TRANSACTION_READ_COMMITTED),

READ_UNCOMMITTED(Connection.TRANSACTION_READ_UNCOMMITTED),

REPEATABLE_READ(Connection.TRANSACTION_REPEATABLE_READ),

SERIALIZABLE(Connection.TRANSACTION_SERIALIZABLE);

通过源码看出首先是从configuration获取environment,接着创建Transaction,

最后通过 configuration.newExecutor创建Executor。

  1. public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
  2.     executorType = executorType == null ? defaultExecutorType : executorType;
  3.     executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
  4.     Executor executor;
  5.     //根据executorType创建不同的Executor对象
  6.     if (ExecutorType.BATCH == executorType) {
  7.       executor = new BatchExecutor(this, transaction);
  8.     } else if (ExecutorType.REUSE == executorType) {
  9.       executor = new ReuseExecutor(this, transaction);
  10.     } else {
  11.       executor = new SimpleExecutor(this, transaction);
  12.     }
  13.     if (cacheEnabled) {
  14.       executor = new CachingExecutor(executor);
  15.     }
  16.     executor = (Executor) interceptorChain.pluginAll(executor);
  17.     return executor;
  18.   }

根据executorType创建对应的Executor,从源码可以看出他有BatchExecutor、ReuseExecutor、CachingExecutor、SimpleExecutor

那么Executor是做什么的呢?

2:Executor

Executor是接口,是对于Statement的封装,我们看下Executor,他是真正执行sql的地方。

  1. public interface Executor {
  2.   ResultHandler NO_RESULT_HANDLER = null;
  3.   int update(MappedStatement ms, Object parameter) throws SQLException;
  4.    List query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey cacheKey, BoundSql boundSql) throws SQLException;
  5.    List query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException;
  6.    Cursor queryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds) throws SQLException;
  7.   List flushStatements() throws SQLException;
  8.   void commit(boolean required) throws SQLException;
  9.   void rollback(boolean required) throws SQLException;
  10.   CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql);
  11.   boolean isCached(MappedStatement ms, CacheKey key);
  12.   void clearLocalCache();
  13.   void deferLoad(MappedStatement ms, MetaObject resultObject, String property, CacheKey key, Class targetType);
  14.   Transaction getTransaction();
  15.   void close(boolean forceRollback);
  16.   boolean isClosed();
  17.   void setExecutorWrapper(Executor executor);
  18. }

上面源码我可以看到Executor接口定义了update 、query、commit、rollback等方法,他的实现类如下图

我们拿其中的SimpleExecutor类里面的doQuery方法看下源码

  1.   @Override
  2.   public  List doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
  3.     Statement stmt = null;
  4.     try {
  5.       Configuration configuration = ms.getConfiguration();
  6.       StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
  7. //StatementHandler封装了Statement, 让 StatementHandler 去处理
  8.       stmt = prepareStatement(handler, ms.getStatementLog());
  9.       return handler.query(stmt, resultHandler);
  10.     } finally {
  11.       closeStatement(stmt);
  12.     }
  13.   }

我们看看StatementHandler 的一个实现类 PreparedStatementHandler(这也是我们最常用的,封装的是PreparedStatement), 看看它使怎么去处理的:

  1.   @Override
  2.   public  List query(Statement statement, ResultHandler resultHandler) throws SQLException {
  3.     String sql = boundSql.getSql();
  4.     //这个和jdbc一样执行sql
  5.     statement.execute(sql);
  6.     //结果交给了ResultSetHandler 去处理
  7.     return resultSetHandler.handleResultSets(statement);
  8.   }

以上是sql底层执行的基本流程,说的直白一点就是所以sql底层都交给了Excutor,我们将在下一讲中分析上一层的调用,也就是Excutor的上层。

我们继续回到openSessionFromDataSource上面来,通过上面的executor的创建最终是创建

new DefaultSqlSession(configuration, executor, autoCommit);到此我们已经完成了SqlSession的创建,后面我们将分析sqlSession.getMapper 也就是Excutor的上层调用。

Mybatis源码分析之SqlSession和Excutor(二)的更多相关文章

  1. 精尽MyBatis源码分析 - SQL执行过程(二)之 StatementHandler

    该系列文档是本人在学习 Mybatis 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释(Mybatis源码分析 GitHub 地址.Mybatis-Spring 源码分析 GitHub ...

  2. 精尽 MyBatis 源码分析 - SqlSession 会话与 SQL 执行入口

    该系列文档是本人在学习 Mybatis 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释(Mybatis源码分析 GitHub 地址.Mybatis-Spring 源码分析 GitHub ...

  3. MyBatis 源码分析

    MyBatis 运行过程 传统的 JDBC 编程查询数据库的代码和过程总结. 加载驱动. 创建连接,Connection 对象. 根据 Connection 创建 Statement 或者 Prepa ...

  4. MyBatis源码分析-MyBatis初始化流程

    MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以对配置和原生Map使用简 ...

  5. MyBatis源码分析-SQL语句执行的完整流程

    MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以对配置和原生Map使用简 ...

  6. MyBatis源码分析(4)—— Cache构建以及应用

    @(MyBatis)[Cache] MyBatis源码分析--Cache构建以及应用 SqlSession使用缓存流程 如果开启了二级缓存,而Executor会使用CachingExecutor来装饰 ...

  7. MyBatis源码分析(2)—— Plugin原理

    @(MyBatis)[Plugin] MyBatis源码分析--Plugin原理 Plugin原理 Plugin的实现采用了Java的动态代理,应用了责任链设计模式 InterceptorChain ...

  8. 【MyBatis源码分析】select源码分析及小结

    示例代码 之前的文章说过,对于MyBatis来说insert.update.delete是一组的,因为对于MyBatis来说它们都是update:select是一组的,因为对于MyBatis来说它就是 ...

  9. MyBatis源码分析之环境准备篇

    前言 之前一段时间写了[Spring源码分析]系列的文章,感觉对Spring的原理及使用各方面都掌握了不少,趁热打铁,开始下一个系列的文章[MyBatis源码分析],在[MyBatis源码分析]文章的 ...

随机推荐

  1. CentOS 6.8 安装 Python3

    由于没有GCC无法编译安装Python3.6, 所以先安装GCC(yum install gcc) 下载地址:https://www.python.org/ftp/python/ 1 tar zxvf ...

  2. Apache Tomcat 9 Installation on Linux (RHEL and clones)

    Apache Tomcat 9 is not available from the standard RHEL distributions, so this article provides info ...

  3. Codeforces 394D Physical Education and Buns 胡搞

    题目链接:点击打开链接 题意:给定n个数的序列(能够排序) 操作一次能够使得某个数++或--. 问最少操作几次使得序列变成一个等差序列 输出: 第一行输出最少操作的次数 第二行输出等差数列里的最小项 ...

  4. Swift - 用CATransform3DMakeRotation实现翻页效果

    Swift - 用CATransform3DMakeRotation实现翻页效果 效果 源码 https://github.com/YouXianMing/Swift-Animations // // ...

  5. maven的groupid和artifactId

    groupid和artifactId被统称为“坐标”是为了保证项目唯一性而提出的,如果你要把你项目弄到maven本地仓库去,你想要找到你的项目就必须根据这两个id去查找. groupId一般分为多个段 ...

  6. 超感猎杀/超感八人组第一季至二季/全集Sense8迅雷下载

    本季 Sense8 (2015)看点:<超感八人组>由沃卓斯基姐弟执导的科幻剧集是Netflix继“纸牌屋第二季”后的又一大手笔制作,讲述未来世界不同地区的8个人因同时目睹同一暴力事件.从 ...

  7. Xcode修改项目的Build Location

    Xcode默认project通过build输出的目录,存放于目录 /Users/用户名/Library/Developer/Xcode/DerivedData/产品名称-hjwqiconnjhpjle ...

  8. 统计学中RR OR AR HR的区别

    一.相对危险度(RR)——队列研究中分析暴露因素与发病的关联程度 队列研究是选择暴露及未暴露于某一因素的两组人群,追踪其各自的发病结局,比较两组发病结局的差异,从而判定暴露因素与疾病有无关联及关联大小 ...

  9. react-router的browserHistory/react-router-dom的BrowserRouter刷新页面404问题解决

    前端解决: '/' 表示把所有的url都发给代理https://api.example.com bypass 表示不需要发给发给代理服务器的条件 如下配置,可以监听https://api.exampl ...

  10. Apache URL重写的配置 及其 apache500错误

    1:如果apache报500错误时 ----->原因:可能是你的ReWrite模块没有打开(有时在apache重装时会忘记打开该模块) 将apache--->httpd.conf文件中Lo ...