[Mybatis源码篇]一、SqlSession的创建过程与作用

结构图

mybatis核心组件之间的关系可以用下图表示:

其中类名前加个”I“表示接口

SqlSessionFactoryBuilder

从图上可以看到,除了Configuration外,每个类的类名都包含一个”SqlSession“,从结构图中也可以看到,我们最终的目标就是为了创建SqlSession,SqlSession可以暂时理解为jdbc中的Connection,通过SqlSession执行sql。

SqlSessionFactoryBuilder顾名思义,是SqlSessionFactory的构建器。

 SqlSession唯一的职责就是构建SqlSessionFactory。构建方式也是多种多样的,可以传入配置文件的Reader对象、输入流,或者直接传入一个封装好的配置类。

Configuration

Configuration类在上面的SqlSessionFactoryBuilder中就已经露面了,这个类中有很多配置项。

这些配置项在启动的时候,会一次性初始化好。(或通过代码、或通过配置文件)

可以看下Configuration与SqlSessionFactory的关系。

 (DefaultSqlSessionFactory是SqlSessionFactory的一个实现类,后面会说到)

DefaultSqlSessionFactory的构造函数只有一个,Configuration作为配置类是必传的。SqlSessionFactory通常与数据源相对应,一个数据源只有一个Factory实例,所以Configuration也同样会常驻内存。

回想初遇mybatis,还没有用上springboot时,常常需要维护一个xml配置文件。

这个配置文件的所有配置项都与Configuration一 一对应。

SqlSessionFactory

SqlSessionFactory是一个接口,有两个实现类SqlSessionManager与DefaultSqlSessionFactory。

职责单一,仅仅用来创建SqlSession。

public interface SqlSessionFactory {

  //8个方法可以用来创建SqlSession实例
  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();

}

创建过程:

  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);
      //然后产生一个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();
    }
  }

大概逻辑如下:

1、通过事务工厂产生一个事务

事务对象有如下部分组成

数据连接对象、数据源、事务隔离信息、是否自动提交。

数据连接对象(Connection)可以没有,因为可以从数据源中获取。

所以我们可以看到,mybatis从配置类中获取到了Environment对象,并拿到了数据源。

2、生成执行器

得到事务对象后,包装一下就成了Executor(执行器)。

Executor负责sql最终的执行。

3、创建SqlSession

SqlSession

终于到主角了,SqlSession。

SqlSession也是接口,只有两个实现类,SqlSessionManager以及DefaultSessionManager。

比较常用的是DefaultSessionManager。

 其实从上面的创建过程就可以看出SqlSession的主要成分了。

new DefaultSqlSession(configuration, executor, autoCommit);

配置类、执行器,最后一个参数表示是否自动提交事务。

意图相当明显了,这分明是让SqlSession做最关键的活——调用executor执行sql语句。

sql语句哪里来?

SqlSession开放的方法接口可以看出,mybatis把常见的一些数据库操作做了封装,不出意外SqlSession就是接待sql的窗口。

我们写一个sql

public interface RoleMapper {
    public Role getRole(@Param("id") Long id);
}

对应的xml

<select id="getRole" parameterType="long" resultMap="roleMap">
        select
        id,role_name as roleName,note from role where id=#{id}
</select>

 最终会调用SqlSession的第二个方法

<T> T selectOne(String statement, Object parameter);

 statement并不是指最终的sql,而是与mybatis中的mapper的方法相对应(mapper接口)。

第二参数通常是map或者pojo对象。比如上述案例中虽然传递只有一个参数id,mybatis也会封装成一个map。见下图:

 通过mapper的方法名找到MappedStatement,并交给执行器executor执行sql。

这一篇算是总览,后面会根据一些具体的实现再做总结。

如有错误,欢迎批评指正!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值