前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >MyBatis源码阅读(四) --- SqlSession的创建过程

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

作者头像
终有救赎
发布2023-12-26 09:21:22
1240
发布2023-12-26 09:21:22
举报
文章被收录于专栏:多线程多线程
一、概述

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

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

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

图片.png
图片.png

以下是SqlSession常见的方法:

代码语言:javascript
复制
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的创建过程
代码语言:javascript
复制
SqlSession sqlSession = sqlSessionFactory.openSession()

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

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

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

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

代码语言:javascript
复制
//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一下,查看具体创建过程各个属性的值:

图片.png
图片.png

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

三、 SqlSession的创建过程流程图
图片.png
图片.png
四、总结

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已经有了比较全面的了解。鉴于笔者水平有限,如果文章有什么错误或者需要补充的,希望小伙伴们指出来,希望这篇文章对大家有帮助。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2023-12-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、概述
  • 二、SqlSession的创建过程
  • 三、 SqlSession的创建过程流程图
  • 四、总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档