Mybatis核心对象和执行流程

Mybatis重要对象

SqlSessionFactory

SqlSessionFactory是mybatis的核心对象,是一个数据库连接的抽象,通过他可以执行一次又一次的数据库操作。SqlSessionFactoryBuilder是专门用于构造SqlSessionFactory的工厂,其通过build函数的重载,支持以不同的方式创建SqlSessionFactory:

image

其中的InputStream是字节流,Reader是字符流,也可以通过自己定义一个Configuration定义数据库连接的相关信息完成SqlSessionFactory的构造。environment用于指定加载哪种环境的配置:


  
    
        ...
    
        ...
  
  
    
        ...
    
        ...
  

SqlSessionFactory的运行周期应该和应用的运行周期一致,同时,没有必要多次创建SqlSessionFactory,实现时可以使用单例。Mybatis提供了一个默认的实现DefaultSqlSessionFactory

在SqlSessionFactory中,通过openSession的重载,提供了创建不同Session的接口:


image

在mybatis-spring包中,将SqlSessionFactory的构造封装到SqlSessionFactoryBean中,默认就被设置成了单例。

image

SqlSession

SqlSessionFactory的产品,当我们在进行一次数据库操作时,都会构造一个Session,把断点定位到DefaultSqlSessionFactory的openSessionFromDataSource方法可以跟踪每一次的数据库操作。SqlSession是非线程安全的,不能被共享。所以,SqlSession的实例不能是静态的,也不能共享到容器中,甚至是类的实例变量也不行。创建SqlSession的过程如下:

  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();
    }
  }

  1. 从配置中获取环境参数
  2. 从环境获取事务
  3. 从环境中获取数据源
  4. 通过配置构造执行器Executor
  5. 构造DefaultSqlSession

其中的执行器Executor是最终操作数据库的对象,SqlSession算是把一次数据操作当做一次回话后对外的封装。有三种类型的Executor:

  public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
    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 {
      executor = new SimpleExecutor(this, transaction);
    }
    if (cacheEnabled) {
      executor = new CachingExecutor(executor);
    }
    executor = (Executor) interceptorChain.pluginAll(executor);
    return executor;
  }

BatchExecutor专门用于执行批量的sql操作,ReuseExecutor会复用statement执行sql操作,而SimpleExecutor就是直接执行sql操作,默认是SIMPLE。最终返回的Executor是一个CachingExecutor,默认情况下Mybatis就开启了执行器缓存,CachingExecutor在查询数据库前先查找缓存,若没找到的话调用传入的Executor对象从数据库查询,并将查询结果存入缓存中。

MappedStatement

MappedStatement是mapper文件中一条操作语句的封装,比如