• MyBatis 源码分析--获取SqlSession


    前言:

    前文我们从源码层面梳理了 SqlSessionFactory 的创建过程,本篇我们继续分析一下 SqlSession 的获取过程。

    初识 MyBatis 【MyBatis 核心概念】

    MyBatis 源码分析–SqlSessionFactory

    案例代码:

    public class MyBatisTest {
        @Test
        public void test() throws IOException {
            //读取配置文件
            InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
            //创建 SqlSessionFactoryBuilder 对象
            SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
            //通过 SqlSessionBuilder 对象 解析 mybatis-config.xml 文件 构建一个SqlSessionFactory 
            SqlSessionFactory sqlSessionFactory = builder.build(is);
            //通过SqlSessionFactory构建一个SqlSession
            SqlSession session = sqlSessionFactory.openSession();
            //通过SqlSession 获取 Mapper 实例
            UserMapper userMapper = session.getMapper(UserMapper.class);
            //获取数据
    		List<User> users = userMapper.findAll();
            //打印输出
            for (User user : users) {
                System.out.println(user);
            }
            //关闭资源
            session.close();
            is.close();
        }
    }
    

    本篇我们将主要对 sqlSessionFactory.openSession() 这句代码进行分析。

    获取 SqlSession 源码分析

    DefaultSqlSessionFactory#openSession 方法源码分析

    DefaultSqlSessionFactory#openSession 方法只是调用了 DefaultSqlSessionFactory#openSessionFromDataSource 方法,并传入了默认的执行器类型、隔离级别、是否自动提交参数。

    //org.apache.ibatis.session.defaults.DefaultSqlSessionFactory#openSession()
    public SqlSession openSession() {
    	//使用默认的执行器类型(默认是SIMPLE) 默认隔离级别 非自动提交 委托给 openSessionFromDataSource 方法
    	return this.openSessionFromDataSource(this.configuration.getDefaultExecutorType(), (TransactionIsolationLevel)null, false);
    }
    

    执行器类型

    • SIMPLE:简单执行器 SimpleExecutor,每执行一条 SQL,都会打开一个 Statement,执行完成后会关闭。
    • REUSE:重用执行器 ReuseExecutor,其内部会缓存一个 Map ,每次编译完成的 Statement 都会进行缓存,不会关闭,可以重复使用。
    • BATCH:批量执行器,基于 JDBC 的 addBatch、executeBatch 功能,只能作用于 insert、update、delete 语句。
    • CachingExecutor:缓存执行器,使用了装饰器模式,在开启缓存的时候,会在上面三种执行器上包装一层 CachingExecutor。
    package org.apache.ibatis.session;
    
    public enum ExecutorType {
        SIMPLE,
        REUSE,
        BATCH;
    
        private ExecutorType() {
        }
    }
    

    DefaultSqlSessionFactory#openSessionFromDataSource 方法源码分析

    DefaultSqlSessionFactory#openSessionFromDataSource 方法逻辑很简单,先获取创建 SqlSession 的必要参数,然后调用 DefaultSqlSession 的构造方法创建了 SqlSession 。

    //org.apache.ibatis.session.defaults.DefaultSqlSessionFactory#openSessionFromDataSource
    private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
    	//事务
    	Transaction tx = null;
    	//SqlSession
    	DefaultSqlSession var8;
    	try {
    		//获取环境
    		Environment environment = this.configuration.getEnvironment();
    		//获取事务工厂
    		TransactionFactory transactionFactory = this.getTransactionFactoryFromEnvironment(environment);
    		//获取一个事务
    		tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
    		//根据 事务 和 执行器类型创建一个执行器
    		Executor executor = this.configuration.newExecutor(tx, execType);
    		//根据配置 执行器 事务提交方式创建一个默认的 SqlSession
    		var8 = new DefaultSqlSession(this.configuration, executor, autoCommit);
    	} catch (Exception var12) {
    		this.closeTransaction(tx);
    		throw ExceptionFactory.wrapException("Error opening session.  Cause: " + var12, var12);
    	} finally {
    		ErrorContext.instance().reset();
    	}
    
    	return var8;
    }
    
    //org.apache.ibatis.session.defaults.DefaultSqlSession#DefaultSqlSession(org.apache.ibatis.session.Configuration, org.apache.ibatis.executor.Executor, boolean)
    public DefaultSqlSession(Configuration configuration, Executor executor, boolean autoCommit) {
    	this.configuration = configuration;
    	this.executor = executor;
    	this.dirty = false;
    	this.autoCommit = autoCommit;
    }
    

    Configuration#newExecutor 方法源码分析

    Configuration#newExecutor 主要是对执行器类型进行判断,然后生成执行器,并通过动态代理得到代理对象,并将执行器加入拦截器链。

    //org.apache.ibatis.session.Configuration#newExecutor
    public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
    	executorType = executorType == null ? this.defaultExecutorType : executorType;
    	executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
    	Object 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 (this.cacheEnabled) {
    		//开启缓存 创建缓存执行器
    		executor = new CachingExecutor((Executor)executor);
    	}
    	//责任链模式 将执行器加入拦截器链 使用JDK动态代理增强所有的拦截器 
    	Executor executor = (Executor)this.interceptorChain.pluginAll(executor);
    	return executor;
    }
    

    获取 SqlSession 的源码很简单,希望可以帮助到有需要的小伙伴。

    欢迎提出建议及对错误的地方指出纠正。

  • 相关阅读:
    linux网络测试命令
    【高并发】通过源码深度解析ThreadPoolExecutor类是如何保证线程池正确运行的
    DAY-6 | 牛客-NC107 寻找峰值:二分法巧得峰值
    redis安装与使用
    我打赌你以前从未使用过TypeScript的断言函数(译)
    mysql 5.7 配置文件开启本地访问
    Spring5框架
    nginx 详细的使用教程
    【数学分析笔记04】数列与数列极限
    虹科示波器 | 汽车免拆检修 | 2014款保时捷卡宴车行驶中发动机偶尔自动熄火
  • 原文地址:https://blog.csdn.net/weixin_42118323/article/details/139663294