zoukankan      html  css  js  c++  java
  • Mybatis源码分析之SqlSession和Excutor(二)

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

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


    还是上篇的代码demo

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

        


    1:openSessionFromDataSource


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


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

     

    说明: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。 

       

    public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
        executorType = executorType == null ? defaultExecutorType : executorType;
        executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
        Executor executor;
        //根据executorType创建不同的Executor对象
        if (ExecutorType.BATCH == executorType) {
          executor = new BatchExecutor(this, transaction);
        } else if (ExecutorType.REUSE == executorType) {
          executor = new ReuseExecutor(this, transaction);
        } else {
          executor = new SimpleExecutor(this, transaction);
        }
        if (cacheEnabled) {
          executor = new CachingExecutor(executor);
        }
        executor = (Executor) interceptorChain.pluginAll(executor);
        return executor;
      }

      

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

    那么Executor是做什么的呢?



    2:Executor


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


    public interface Executor {
      ResultHandler NO_RESULT_HANDLER = null;
      int update(MappedStatement ms, Object parameter) throws SQLException;
       List query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey cacheKey, BoundSql boundSql) throws SQLException;
       List query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException;
       Cursor queryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds) throws SQLException;
      List flushStatements() throws SQLException;
      void commit(boolean required) throws SQLException;
      void rollback(boolean required) throws SQLException;
      CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql);
      boolean isCached(MappedStatement ms, CacheKey key);
      void clearLocalCache();
      void deferLoad(MappedStatement ms, MetaObject resultObject, String property, CacheKey key, Class targetType);
      Transaction getTransaction();
      void close(boolean forceRollback);
      boolean isClosed();
      void setExecutorWrapper(Executor executor);
    }

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



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


      @Override
      public  List 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);
    //StatementHandler封装了Statement, 让 StatementHandler 去处理
          stmt = prepareStatement(handler, ms.getStatementLog());
          return handler.query(stmt, resultHandler);
        } finally {
          closeStatement(stmt);
        }
      }

     

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

      

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

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



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

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







  • 相关阅读:
    小米华为vivooppo手机记录隐私证据查询
    【类型】在资源管理器中,对文件按照“类型”排序,实际上 就是按照文件扩展名排序。
    【转载】在python的class中的,self到底是什么?
    【转载】Windows 10系统默认将画面显示比例调整至125%或150%,最高分辨率已经达到3840×2160(4K)这一级别。
    [转载]层叠与并排win10
    【转载】浏览器测试工具有哪些 浏览器安全性能内核兼容测试工具推荐
    【转载】我常用的地址,现记录一下,遗忘时或换电脑时查询
    【转载】浏览器测试基本跑分网站
    【转载】Python 代码调试技巧
    HDU 2446 Shell Pyramid(二分查找 数学)
  • 原文地址:https://www.cnblogs.com/jeffen/p/6277602.html
Copyright © 2011-2022 走看看