mybatis源码分析:从SqlSessionFactory说起

Scroll Down

1、Mybatis的执行过程

用户端使用SqlSession代码如下:

// 获取mybatis运行时配置文件的内容
Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
// 创建SqlSessionFactory对象
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
// 根据SqlSessionFactory创建SqlSession对象
SqlSession sqlSession = factory.openSession();
// 通过SqlSession对象获取UserMapper接口的代理实现类
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 执行增强后的用户代码获取执行结果
User user = userMapper.getUserById(1);
System.out.println(user);
List<User> users = userMapper.listAllUser();
System.out.println(users);

2、创建SqlSessionFactory对象

SqlSessionFactory接口代码如下:

public interface SqlSessionFactory {

  SqlSession openSession();

  SqlSession openSession(boolean autoCommit);

  SqlSession openSession(Connection connection);

  SqlSession openSession(TransactionIsolationLevel level);

  SqlSession openSession(ExecutorType execType);

  SqlSession openSession(ExecutorType execType, boolean autoCommit);

  SqlSession openSession(ExecutorType execType, TransactionIsolationLevel level);

  SqlSession openSession(ExecutorType execType, Connection connection);

  Configuration getConfiguration();

}

SqlSessionFactory接口中主要定义了两类方法:
(1)、openSession()方法:用来获取SqlSession对象。SqlSession对象是一个装饰器用来提供封装对SQL执行的细节的类。后续会详细讲述工作原理。
(2)、getConfiguration()方法:用来获取Configuration对象。
SqlSessionFactory接口有两个实现类:
image.png
代码中使用的是SqlSessionFactoryBuilder的build来创建SqlSessionFactory类。代码如下:

public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
    try {
      // 创建XMLConfigBuilder实例,该实例用于创建Mybatis运行时配置类Configuration
      XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
      // 构建SqlSessionFactory
      return build(parser.parse());
    } catch (Exception e) {
      throw ExceptionFactory.wrapException("Error building SqlSession.", e);
    } finally {
      ErrorContext.instance().reset();
      try {
        reader.close();
      } catch (IOException e) {
        // Intentionally ignore. Prefer previous error.
      }
    }
  }

build()方法如下所示:

public SqlSessionFactory build(Configuration config) {
    // Mybatis中默认使用DefaultSqlSessionFactory
    return new DefaultSqlSessionFactory(config);
}

运行流程如下图所示:
mybatisSqlSessionFactoryCreator.png

DefaultSqlSessionFactory中openSession()方法如下:

@Override
public SqlSession openSession() {
    return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
}

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

至此SqlSession已经创建完成。