MyBatis 一句sql的执行流程

未完待接着往里面更新

在上一会MyBatis解析自身配置文件记录中我们简单了解了一下框架解析配置信息的流程,下面我们看看一句sql是怎么执行的;

项目代码还是以官方的mybatis-3-mybatis-3.3.0项目为基础

  • 入口:
    public class SqlSessionTest extends BaseDataTest {
  private static SqlSessionFactory sqlMapper;

  @BeforeClass
  public static void setup() throws Exception {
    createBlogDataSource();
    final String resource = "org/apache/ibatis/builder/MapperConfig.xml";
    final Reader reader = Resources.getResourceAsReader(resource);
    sqlMapper = new SqlSessionFactoryBuilder().build(reader);
  }  
  
  @Test
  public void shouldSelectAllAuthors() throws Exception {
    SqlSession session = sqlMapper.openSession(TransactionIsolationLevel.SERIALIZABLE);
    try {
      List<Author> authors = session.selectList("org.apache.ibatis.domain.blog.mappers.AuthorMapper.selectAllAuthors");
      assertEquals(2, authors.size());
    } finally {
      session.close();
    }
  }
  • 第一步我们先看看SqlSessionFactory sqlMapper;用的是:
    package org.apache.ibatis.session;
    public class SqlSessionFactoryBuilder {
    
     public SqlSessionFactory build(Configuration config) {
        return new DefaultSqlSessionFactory(config);//实现
      }
    package org.apache.ibatis.session.defaults;
    public class DefaultSqlSessionFactory implements SqlSessionFactory {

  private final Configuration configuration;

  public DefaultSqlSessionFactory(Configuration configuration) {
    this.configuration = configuration;
  }
  • 之后看看session是怎么获取到的:
    SqlSession session = sqlMapper.openSession(TransactionIsolationLevel.SERIALIZABLE);

    调的是
    SqlSession openSession(TransactionIsolationLevel level);
    接口
    具体的事务级别:

    /**
     * A constant indicating that
     * dirty reads, non-repeatable reads and phantom reads are prevented.
     * This level includes the prohibitions in
     * <code>TRANSACTION_REPEATABLE_READ</code> and further prohibits the
     * situation where one transaction reads all rows that satisfy
     * a <code>WHERE</code> condition, a second transaction inserts a row that
     * satisfies that <code>WHERE</code> condition, and the first transaction
     * rereads for the same condition, retrieving the additional
     * "phantom" row in the second read.
     */
    int TRANSACTION_SERIALIZABLE     = 8;
    
    • DefaultSqlSessionFactory实现
    @Override
    public SqlSession openSession(TransactionIsolationLevel level) {
    //这里看到我们上一篇说过的很重要的configuration出现了,我们要拿东西了(看看方法名称基本就不想看了吧:)),注意我们这里的level是SERIALIZABLE(Connection.TRANSACTION_SERIALIZABLE);->8级别,而配置对象中ExecutorType是?
    //ExecutorType.SIMPLE -> 0
    //false 标识不自动提交
    return openSessionFromDataSource(configuration.getDefaultExecutorType(), level, false);
    }
    
    private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
    Transaction tx = null;
    try {
      final Environment environment = configuration.getEnvironment();
      final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);//得到的是org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory
      tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);//环境中存储的是包裹了org.apache.derby.jdbc.EmbeddedDriver驱动的的org.apache.ibatis.datasource.unpooled.UnpooledDataSource实现,得到一个org.apache.ibatis.transaction.jdbc.JdbcTransaction
      final Executor executor = configuration.newExecutor(tx, execType);//新建一个框架自身的org.apache.ibatis.executor.Executor,实现executor = new SimpleExecutor(this, transaction);,框架的executor定义了我们可以执行的sql方法,比如update、query等;其下将会保持:
      /*
        public abstract class BaseExecutor implements Executor {
    
    private static final Log log = LogFactory.getLog(BaseExecutor.class);
    
    protected Transaction transaction;
    protected Executor wrapper;
    
    protected ConcurrentLinkedQueue<DeferredLoad> deferredLoads;
    protected PerpetualCache localCache;
    protected PerpetualCache localOutputParameterCache;
    protected Configuration configuration;
    
    protected int queryStack = 0;
    private boolean closed;
    
    protected BaseExecutor(Configuration configuration, Transaction transaction) {
    this.transaction = transaction; 一个org.apache.ibatis.transaction.jdbc.JdbcTransaction事务对象
    this.deferredLoads = new ConcurrentLinkedQueue<DeferredLoad>();
    this.localCache = new PerpetualCache("LocalCache");
    this.localOutputParameterCache = new PerpetualCache("LocalOutputParameterCache");
    this.closed = false;
    this.configuration = configuration; 全局配置对象
    this.wrapper = this;
    }
    
    因为我们主配置文件中设置了<setting name="cacheEnabled" value="true"/>,那么SimpleExecutor还会被封装成:
    if (cacheEnabled) {
      executor = new CachingExecutor(executor); 包裹器
    }
    executor = (Executor) interceptorChain.pluginAll(executor); 这行代码很关键,将会把这个可执行对象放入我们的插件拦截器中,即调用Object plugin(Object target)接口,如果我们配置了拦截器,这里可能还要被代理包裹一层,返回持有executor的动态代理对象
    return executor;
    }
      */
    
      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();
    }
    }
    

你可能感兴趣的:(MyBatis 一句sql的执行流程)