前言:
前文我们从源码层面梳理了 SqlSessionFactory 的创建过程,本篇我们继续分析一下 SqlSession 的获取过程。
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<String, Statement> ,每次编译完成的 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 的源码很简单,希望可以帮助到有需要的小伙伴。
欢迎提出建议及对错误的地方指出纠正。
标签:执行器,session,--,executorType,SqlSession,源码,executor From: https://blog.csdn.net/weixin_42118323/article/details/139663294