转载

Mybatis源码分析(五):获取sqlSession

构建sqlSessionFactory下一步就是获取sqlSession,代码如下:

SqlSession sqlSession = sqlSessionFactory.openSession();

SqlSessionFactory有两个实现类,SqlSessionManager和DefaultSqlSessionFactory。

Mybatis源码分析(五):获取sqlSession

由上篇文章可知,在

SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

中,new了一个DefaultSqlSessionFactory对象,我们详细介绍下DefaultSqlSessionFactory的主要方法。

5.1 DefaultSqlSessionFactory

DefaultSqlSessionFactory是一个具体工厂类,主要提供了两种创建 DefaultSqlSession方式。一种方式是通过数据源获取数据库连接并创建Excutor 对象以及DefaultSqlSession对象,源代码如下:

private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
    Transaction tx = null;
    try {
      final Environment environment = configuration.getEnvironment();
      final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
      //根据DataSource对象创建Transaction对象
      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();
    }
  }

另一种方式是根据用户提供的连接对象获取数据库连接并创建Excutor 对象以及DefaultSqlSession对象,其中的自动提交方式也是采用的Connection对象中的。源代码如下:

private SqlSession openSessionFromConnection(ExecutorType execType, Connection connection) {
    try {
      boolean autoCommit;
      try {
        //使用Connection对象的自动提交方式
        autoCommit = connection.getAutoCommit();
      } catch (SQLException e) {
        // Failover to true, as most poor drivers
        // or databases won't support transactions
        autoCommit = true;
      }
      final Environment environment = configuration.getEnvironment();
      final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
      //根据Connection对象创建Transaction对象
      final Transaction tx = transactionFactory.newTransaction(connection);
      final Executor executor = configuration.newExecutor(tx, execType);
      return new DefaultSqlSession(configuration, executor, autoCommit);
    } catch (Exception e) {
      throw ExceptionFactory.wrapException("Error opening session.  Cause: " + e, e);
    } finally {
      ErrorContext.instance().reset();
    }
  }

二者的区别只有上面两点,即注释中的语句。

本文的例子调用的是第一个方法,该方法主要分四步:

1.从configuration中获取Environment对象。

2.从Environment对象获取TransactionFactory对象。

3.使用TransactionFactory对象创建Transaction对象。

4.根据Transaction对象创建Executor对象。

5.根据Executor对象创建DefaultSqlSession对象。

5.2 Environment

Environment对象是XMLConfigBuilder对象的parse()方法进行构造的。具体的执行者是XMLConfigBuilder内部的私有方法environmentsElement()。它有以下几个字段:

private final String id;
  private final TransactionFactory transactionFactory;
  private final DataSource dataSource;

对应配置文件中的<environment>节点。

<!-- id:唯一标识 -->
        <environment id="test">
            <!-- 事务管理器,JDBC类型的事务管理器 -->
            <transactionManager type="JDBC" />
            <!-- 数据源,池类型的数据源 -->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver" />
                <property name="url" value="jdbc:mysql://xxx/xxx" />
                <property name="username" value="xxx" />
                <property name="password" value="xxx" />
            </dataSource>
        </environment>

通过断点可以看到,字段的值和上面的配置一一对应。

Mybatis源码分析(五):获取sqlSession

5.3 TransactionFactory与Transaction

TransactionFactory对象是从上面的Environment对象获取的。TransactionFactory是创建Transaction对象的工厂,它有两个实现类。一个是JdbcTransactionFactory用来创建JdbcTransaction,另一个是ManagedTransactionFactory用外创建ManagedTransaction。

Mybatis源码分析(五):获取sqlSession

Transaction有两个实现类一个是JdbcTransaction,另一个是ManagedTransaction。

Mybatis源码分析(五):获取sqlSession

本文例子配置文件中<transactionManager type="JDBC" />

所以使用的是JdbcTransaction.

Transaction主要有以下几个接口。

Mybatis源码分析(五):获取sqlSession

JdbcTransaction主要的字段如下:

//数据库连接
  protected Connection connection;
  //数据源
  protected DataSource dataSource;
  //数据库隔离级别
  protected TransactionIsolationLevel level;
  //是否自动提交
  protected boolean autoCommit;

ManagedTransaction和JdbcTransaction比较类似,但是没有实现commit()和rollback()方法。

5.4 Executor

在openSessionFromDataSource方法中创建Transaction对象之后,会根据tx创建一个Executor,语句如下:

final Executor executor = configuration.newExecutor(tx, execType);

configuration的newExecutor方法主要作用是根据execType来创建不同类型的Executor对象,并通过代理的方法执行interceptor。代码如下:

public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
    //如果没有指定executorType,则使用ExecutorType.SIMPLE,
    //defaultExecutorType是一个常量,值也是ExecutorType.SIMPLE
    executorType = executorType == null ? defaultExecutorType : executorType;
    executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
    Executor executor;
    if (ExecutorType.BATCH == executorType) {
      executor = new BatchExecutor(this, transaction);
    } else if (ExecutorType.REUSE == executorType) {
      executor = new ReuseExecutor(this, transaction);
    } else { //由于ExecutorType.SIMPLE == executorType,所以走这个分支
      executor = new SimpleExecutor(this, transaction);
    }
    if (cacheEnabled) {//默认是true,可以通过<settings>标签改变
      executor = new CachingExecutor(executor);
    }
    executor = (Executor) interceptorChain.pluginAll(executor);
    return executor;
  }

由上面代码看出先new了一个SimpleExecutor,然后被CachingExecutor代理,然后被interceptor代理。假设有三个拦截器,配置顺序为interceptor1、interceptor2、interceptor3最后的执行关系是这样的:interceptor3(interceptor2(interceptor1(CachingExecutor(SimpleExecutor()))))

plugin3 before
plugin2 before
plugin1 before
caching ...
simpleExecutor ...
plugin1 after
plugin2 after
plugin3 after

5.5 DefaultSqlSession

最后一步是根据Executor对象创建DefaultSqlSession对象。

DefaultSqlSession就SqlSession的默认实现类,属于接口层。主要功能是数据库表的增删改查。

原文  https://segmentfault.com/a/1190000023307710
正文到此结束
Loading...