MyBatis源码解读(二)会话创建

MyBatis源码解读(二)会话创建

MyBatis源码解读之会话创建

会话创建过程

程序每一次操作数据库,都需要创建一个会话,我们用openSession() 方法来创建。

1
SqlSession session = sqlSessionFactory.openSession()

这里用到了上一步创建的DefaultSqlSessionFactory,在 openSessionFromDataSource() 方法中创建。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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();
}
}

这个会话里面,需要包含一个Executor用来执行SQL。Executor又要指定事务类型和执行器的类型。

所以我们会先从Configuration里面拿到Enviroment,Enviroment里面就有事务工厂。

1、创建Transaction

这里会从Environment对象中取出一个TransactionFactory,它是解析<environments>标签的时候创建的。

1
2
3
4
5
6
private TransactionFactory getTransactionFactoryFromEnvironment(Environment environment) {
if (environment == null || environment.getTransactionFactory() == null) {
return new ManagedTransactionFactory();
}
return environment.getTransactionFactory();
}

事务工厂类型可以配置成JDBC或者MANAGED。

属性 产生工厂类 产生事务
JDBC JdbcTransactionFactory JdbcTransaction
MANAGED ManagedTransactionFactory ManagedTransaction

如果配置的是JDBC,则会使用Connection对象的commit() 、rollback()、close()管理事务。

如果配置成MANAGED,会把事务交给容器来管理,比如JBOSS,Weblogic。

因为我们跑的是本地程序,如果配置成MANAGE不会有任何事务。

如果是Spring+MyBatis,则没有必要配置,因为我们会直接在applicationContext.xml里面配置数据源和事务管理器,覆盖MyBatis的配置。

2、创建Executor

使用newExecutor方法创建:

1
2
// 根据事务工厂和默认的执行器类型,创建执行器 >>
final Executor executor = configuration.newExecutor(tx, execType);

可以分成三步。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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) { // 针对statement对象作缓存
executor = new ReuseExecutor(this, transaction);
} else {
// 默认 SimpleExecutor 每次执行sql操作都会创建一个新的Statement对象
executor = new SimpleExecutor(this, transaction);
}
// 二级缓存开关,settings 中的 cacheEnabled 默认是 true
if (cacheEnabled) {
executor = new CachingExecutor(executor);
}
// 植入插件的逻辑,至此,四大对象已经全部拦截完毕
executor = (Executor) interceptorChain.pluginAll(executor);
return executor;
}

(1) 创建执行器

Executor的基本类型有三种:SIMPLE、BATCH、REUSE,默认是SIMPLE(settingsElement() 读取默认值)

1
2
3
4
5
6
7
8
if (ExecutorType.BATCH == executorType) {
executor = new BatchExecutor(this, transaction);
} else if (ExecutorType.REUSE == executorType) { // 针对statement对象作缓存
executor = new ReuseExecutor(this, transaction);
} else {
// 默认 SimpleExecutor 每次执行sql操作都会创建一个新的Statement对象
executor = new SimpleExecutor(this, transaction);
}

(2)缓存装饰

如果cacheEnabled=true,会用装饰器模式对executor进行装饰。

1
2
3
4
// 二级缓存开关,settings 中的 cacheEnabled 默认是 true
if (cacheEnabled) {
executor = new CachingExecutor(executor);
}

(3)插件代理

装饰完毕后,会执行:

1
2
// 植入插件的逻辑,至此,四大对象已经全部拦截完毕
executor = (Executor) interceptorChain.pluginAll(executor);

此处会对executor植入插件逻辑。

总结

最终返回DefaultSqlSession,它的属性包括Configuration、Executor对象。

1
return new DefaultSqlSession(configuration, executor, autoCommit);

创建会话的过程,我们获得了一个DefaultSqlSession,里面包含了一个, Executor是SQL的实际执行对象。

打赏

请我喝杯咖啡吧~

支付宝
微信