上接 《真的,MyBatis 核心源码入门看这个就够了(一)》
2 SqlSession
SqlSession对象的创建过程
程序每一次操作数据库,都需要创建一个会话,我们用openSession() 来创建。
在上一篇文章的demo:
```java
@org.junit.jupiter.api.Test
void queryBySn() throws IOException {
//1 读取配置文件
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
//2 加载解析配置文件并获取SqlSessionFactory对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
//3 获取SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//4 通过SqlSession中提供的API方法来操作数据库
DeviceMapper deviceMapper = sqlSession.getMapper(DeviceMapper.class);
Device device = deviceMapper.queryBySn(Device.builder().sn("2234567").build());
System.out.println(device);
//5 关闭会话
sqlSession.close();
}
通过 DefaultSqlSessionFactory
的openSession 来创建。
public class DefaultSqlSessionFactory implements SqlSessionFactory {
......
@Override
public SqlSession openSession() {
return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
}
......
}
首先会获取默认的执行器类型,默认的是simple
public class Configuration {
......
protected ExecutorType defaultExecutorType = ExecutorType.SIMPLE;
.....
}
继续进入到 DefaultSqlSessionFactory的 openSessionFromDataSource方法:
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);
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();
}
}
我们在解析 environment 标签的时候,创建了TransactionFactory对象。
public class XMLConfigBuilder extends BaseBuilder {
......
private void environmentsElement(XNode context) throws Exception {
if (context != null) {
if (environment == null) {
environment = context.getStringAttribute("default");
}
for (XNode child : context.getChildren()) {
String id = child.getStringAttribute("id");
if (isSpecifiedEnvironment(id)) {
// 事务工厂
TransactionFactory txFactory = transactionManagerElement(child.evalNode("transactionManager"));
......
根据事务工厂和默认的执行器类型,创建执行器:
final Executor executor = configuration.newExecutor(tx, execType);
public class Configuration {
......
public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
executorType = executorType == null ? defaultExecutorType : executorType;
executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
Executor executor;
if (ExecutorType.BATCH == executorType) {
executor = new BatchExecutor(this, transaction);
} else if (ExecutorType.REUSE == executorType) {
executor = new ReuseExecutor(this, transaction);
} else {
// 默认 SimpleExecutor
executor = new SimpleExecutor(this, transaction);
}
// 二级缓存开关,settings 中的 cacheEnabled 默认是 true
if (cacheEnabled) {
executor = new CachingExecutor(executor);
}
// 植入插件的逻辑,至此,四大对象已经全部拦截完毕
executor = (Executor) interceptorChain.pluginAll(executor);
return executor;
}
......
}
最后返回的是一个 DefaultSqlSession对象。
return new DefaultSqlSession(configuration, executor, autoCommit);
在这个DefaultSqlSession对象中包括了Configuration 和 Executor对象。
以上2 章节创建会话的过程中,我们获得了一个DefaultSqlSession,里面包含了一个Executor,Executor是SQL的实际执行对象。