• Mybatis3详解(十七)——Mybatis运行原理之SqlSession的构建过程


    1、SqlSession的构建过程

           在上一章,详细的介绍了SqlSessionFactory的构建过程,它是用来获取SqlSession对象的,所以本章节就主要讲述SqlSession的构建过程。

           程序代码的入口:

    image

           我们知道SqlSession对象是通过SqlSessionFactory的openSession()方法获取的,所以我们先来看一下SqlSessionFactory接口中的方法:

    image

           可以发现SqlSessionFactory接口提供一系列重载的openSession方法,其参数如下(这些参数的意义会在后面介绍):

    • boolean autoCommit:是否开启JDBC事务的自动提交,默认为false。
    • Connection:提供连接。
    • TransactionIsolationLevel:定义事务隔离级别。
    • ExecutorType:定义执行器类型。

           SqlSessionFactory接口的实现类为DefaultSqlSessionFactory类。所以我们去DefaultSqlSessionFactory实现类中查看重写的openSession()方法:

       //以无参的openSession()方法为例
       public SqlSession openSession() {
        return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
      }

           通过查看其它重写的方法,会发现最终都调用了openSessionFromDataSource方法,所以继续进入方法:

      private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
        Transaction tx = null;
        try {
    	  // 获取Configration全局配置中的environment的配置
          final Environment environment = configuration.getEnvironment();
    	  // 通过environment配置构建transactionFactory对象
          final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
    	  // 从工厂中获取一个事务实例
          tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
    	  // 通过configuration构建Executor执行器对象
          final Executor executor = configuration.newExecutor(tx, execType);
    	  // 返回SqlSession的默认实现类DefaultSqlSession
          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();
        }
      }

           上面代码中有一行是通过configuration.newExecutor(tx,execType)来构建Executor执行器对象,这一步非常重要,因为MyBatis 中所有的 Mapper 语句的执行都是通过 Executor 来执行的,它负责SQL语句的生成和查询缓存的维护 。所以我们看一下它是怎么创建的,这里调用了Configuration类中newExecutor()方法。

       // ====== Configuration 类中的方法 ======
       public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
        executorType = executorType == null ? defaultExecutorType : executorType;
        executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
    	// 定义Executor执行器
        Executor executor;
        // 判断执行器的类型,根据传入executorType参数
        // BatchExecutor:批量执行器
        // ReuseExecutor:会执行预处理的执行器
        // SimpleExecutor:简单的执行器
        if (ExecutorType.BATCH == executorType) {
          executor = new BatchExecutor(this, transaction);
        } else if (ExecutorType.REUSE == executorType) {
          executor = new ReuseExecutor(this, transaction);
        } else {
    	  // 如果没有配置,默认就为SimpleExecutor
          executor = new SimpleExecutor(this, transaction);
        }
    	//如果开启了二级缓存,则使用CachingExecutor 来包装executor,
    	//在查询之前都会先查询缓存中是否有对应的数据,包装的过程使用了装饰者模式
        if (cacheEnabled) {
          executor = new CachingExecutor(executor);
        }
    	// 最后使用每个拦截器重新包装executor并返回
        executor = (Executor) interceptorChain.pluginAll(executor);
    	//返回创建好的Executor执行器
        return executor;
      }

           注意(这里了解就好):executor = (Executor) interceptorChain.pluginAll(executor);这个是Mybatis中的插件,它将构建一层层的代理对象,可以在执行真正的Executor的方法前,执行配置在插件中的方法对核心代码进行修改,所以不要轻易使用插件,这里用的是责任链模式。Mybatis在实例化Executor、ParameterHandler、ResultSetHandler、StatementHandler四大接口对象的时候都是调用interceptorChain.pluginAll() 方法插入进去的。其实就是循环执行拦截器链所有的拦截器的plugin() 方法。


           Executor 对象创建完之后会以参数的形式传入DefaultSqlSession的构造方法中,从而完成SqlSession对象的创建并且返回。

    image

           至此SqlSession对象的创建过程也就结束了。

           SqlSession对象构建过程中的时序图:

    image

    2、重载的openSession方法参数介绍

           上面程序入口我们调用的是无参数的openSession()方法,那么其它重载的方法有什么用呢?这里来介绍一下有参方法中的参数含义,有四类分别为。

    • boolean autoCommit:是否开启JDBC事务的自动提交,默认为false。
    • Connection:提供连接。
    • TransactionIsolationLevel:定义事务隔离级别。
    • ExecutorType:定义执行器类型。


             ①、boolean autoCommit:是否自动提交事物,默认为false。

             如果为true就自动提交事务,后面就不要写commit()方法提交了。


             ②、TransactionIsolationLevel :事务隔离级别类,它是一个枚举类型。

      image

             可以发现默认五种隔离级别:

      1. NONE(Connection.TRANSACTION_NONE):无隔离级别
      2. READ_COMMITTED(Connection.TRANSACTION_READ_COMMITTED):读取提交内容
      3. READ_UNCOMMITTED(Connection.TRANSACTION_READ_UNCOMMITTED):读取未提交内容
      4. REPEATABLE_READ(Connection.TRANSACTION_REPEATABLE_READ):可重复读
      5. SERIALIZABLE(Connection.TRANSACTION_SERIALIZABLE):可串行化


             ③、Connection:提供连接对象。

             如果使用这种方式会优先使用这里面的数据库连接对象。如:

      image


          ④、ExecutorType :执行器类型,它是一个枚举类型。

      image

             它主要用来判断使用哪种类型的执行器Executor,因为SqlSession是真正来执行Java与数据库交互的对象,提供了查询(query)、更新(update)等方法,主要有三种类型:

      1. SIMPLE:简易执行器,如果不配置类型,就是默认执行器
      2. REUSE:能过执行重用预处理语句的执行器
      3. BATCH:执行器重用语句和批量更新,批量专用的执行

             在上面创建Executor执行器的代码中已经进行了判断。所以这里就不再多说了。

      image

             -------------------------------------------------------------------------

      image

    • 相关阅读:
      软件测试工具
      Linux笔记
      Google Test
      字典dict()
      元组tuple 可迭代对象
      列表list
      一些总结
      format()
      列表list
      format() expandtabs() 输入表格数据
    • 原文地址:https://www.cnblogs.com/tanghaorong/p/14083400.html
    Copyright © 2020-2023  润新知