MyBatis源码阅读(四) --- SqlSession的创建过程

欢迎关注MyBatis源码阅读专栏,持续更新中~~

一、概述

前面一篇文章我们详细分析了SqlSessionFactory的创建过程,既然SqlSessionFactory有了,那么我们就可以通过sqlSessionFactory.openSession()来开启一个会话了,进而实现对数据库的操作,那么sqlSessionFactory.openSession()到底干了哪些事情呢?本篇文章就来详细了解一下。

SqlSession是Mybatis的高级接口,类似于JDBC操作的connection对象,它包装了数据库连接,通过这个接口我们可以实现增删改查,提交/回滚事务,关闭连接,获取代理类等操作。SqlSession是线程不安全的,每个线程都会有自己唯一的SqlSession,不同线程间调用同一个SqlSession会出现问题,因此在使用完后需要及时关闭。

SqlSession是个接口,其默认实现是DefaultSqlSession,另外一个子类是SqlSessionManager。

以下是SqlSession常见的方法:

java 复制代码
public interface SqlSession extends Closeable {
 
  /**
  * 查询一个结果对象
  **/ 
  <T> T selectOne(String statement, Object parameter);
  
   /**
  * 查询一个结果集合
  **/ 
  <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds);
  
   /**
  * 查询一个map
  **/ 
  <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds);
 
   /**
  * 查询游标
  **/ 
  <T> Cursor<T> selectCursor(String statement, Object parameter, RowBounds rowBounds);
 
  void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler);
  
     /**
  * 插入
  **/ 
  int insert(String statement, Object parameter);
 
    /**
  * 修改
  **/ 
  int update(String statement, Object parameter);
 
  /**
  * 删除
  **/
  int delete(String statement, Object parameter);
 
   /**
  * 提交事物
  **/
  void commit(boolean force);
  
   /**
  * 回滚事物
  **/
  void rollback(boolean force);
 
  List<BatchResult> flushStatements();
 
  void close();
 
  void clearCache();
 
  Configuration getConfiguration();
 
   /**
  * 获取映射代理类
  **/
  <T> T getMapper(Class<T> type);
 
   /**
  * 获取数据库连接
  **/
  Connection getConnection();
}

可以看到,SqlSession可以实现增删改查,提交/回滚事务,关闭连接,获取代理类等操作,下面就来看下SqlSession详细的创建过程。

二、SqlSession的创建过程

ini 复制代码
SqlSession sqlSession = sqlSessionFactory.openSession()

通过sqlSessionFactory的openSession()开启一个会话。

DefaultSqlSessionFactory中有两种创建会话的方式:

  • openSessionFromDataSource:从数据源中获取SqlSession对象,SqlSession实际是对数据库连接的一层包装,数据库连接是个珍贵的资源,如果频繁的创建销毁将会影响吞吐量,这种方式就是从数据库连接池中获取一个连接,然后包装成一个SqlSession。
  • openSessionFromConnection:由已有连接获取SqlSession对象。
java 复制代码
//默认使用的是DefaultSqlSessionFactory
//org.apache.ibatis.session.defaults.DefaultSqlSessionFactory#openSession()
@Override
public SqlSession openSession() {
  //configuration中有默认执行器类型,是SIMPLE简单类型执行器(SimpleExecutor)
  //从数据库连接池中获取一个连接,然后包装成一个SqlSession对像
  //可以复用数据库连接
  return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
}

这里我们以openSessionFromDataSource为例:从数据源连接池获取一个SqlSession会话

java 复制代码
//org.apache.ibatis.session.defaults.DefaultSqlSessionFactory#openSessionFromDataSource
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
  //事务对象
  Transaction tx = null;
  try {
    //从configuration对象中获取到我们之前解析的environment环境信息
    final Environment environment = configuration.getEnvironment();
    //事务工厂,这里是JbdcTransactionFactory工厂类
    final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
    //通过事务工厂创建JbdcTransaction事务,传入数据源等信息
    tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
    //创建Executor执行器
    final Executor executor = configuration.newExecutor(tx, execType);
    //创建DefaultSqlSession会话,传入Configuration、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();
  }
}

我们看到,创建SqlSession主要需要下面几个东西:

  • 【a】environment

环境对象,这是在mybatis-config.xml中配置的,主要用来生成TransactionFactory,而TransactionFactory是用来生成Transaction事务的。

  • 【b】Transaction

事务对象,我们都知道sql执行时涉及到事务,需要提交或回滚什么的。创建Transaction事务对象,需要传入我们在mybatis-config.xml中配置的数据源信息(从environment获取,因为之前解析XML的时候保存进去了),通过这些参数,transactionFactory就可以生成Transaction。

  • 【c】executor

执行器,它是一个接口,是Mybatis的核心执行器,相当于jdbc中的statement,发送sql语句并执行。executor的继承图如下所示,默认使用的是SimpleExecutor简单类型的执行器。

  • 【d】configuration

全局配置信息

我们Debug一下,查看具体创建过程各个属性的值:

至此,我们的SqlSession对象就创建成功了,其中还涉及到Executor执行器的创建过程,暂且先跳过,后面专门使用一篇文章分析Executor的原理。

三、 SqlSession的创建过程流程图

四、总结

openSessionFromDataSource 主要经历了以下几步:

  1. 从获取configuration中获取Environment对象,Environment包含了数据库配置;
  2. 从Environment获取DataSource数据源;
  3. 从DataSource数据源中获取Connection连接对象;
  4. 从DataSource数据源中获取TransactionFactory事务工厂,并创建事务Transaction对象;
  5. 基于事务Transaction创建Executor对象;
  6. 返回创建好的DefaultSqlSession对象,里面包含configuration和Executor对象;

本篇文章主要总结了Mybatis中SqlSession会话的创建过程,相信大家对SqlSession已经有了比较全面的了解。鉴于笔者水平有限,如果文章有什么错误或者需要补充的,希望小伙伴们指出来,希望这篇文章对大家有帮助。

相关推荐
工业甲酰苯胺16 分钟前
Tomcat的事件监听机制:观察者模式
java·观察者模式·tomcat
007张三丰1 小时前
系统架构设计师范文3:论基于架构的软件设计方法及应用(ABSD)
架构·软考·系统架构设计师·架构演化·论文高级·absd
QC班长7 小时前
Maven公司私库配置踩坑点
java·服务器·maven·intellij-idea
Makoto_Kimur7 小时前
java开发面试-AI Coding速成
java·开发语言
wuqingshun3141598 小时前
说说mybatis的缓存机制
java·缓存·mybatis
空中海8 小时前
Kubernetes 生产实践、可观测性与扩展入门
java·贪心算法·kubernetes
Agent手记8 小时前
制造业数字化升级:生产全流程企业级智能体落地解决方案 —— 基于LLM+超自动化全栈架构的智改数转深度实战
运维·ai·架构·自动化
Devin~Y9 小时前
大厂Java面试实录:Spring Boot/Cloud、Kafka、Redis、K8s 与 Spring AI(RAG/Agent)三轮连环问
java·spring boot·redis·mysql·spring cloud·kafka·kubernetes
bLEd RING9 小时前
SpringBoot3.3.0集成Knife4j4.5.0实战
java
小松加哲9 小时前
Spring MVC 核心原理全解析
java·spring·mvc