在上一篇文章中,解析了SqlSessionFactory的创建过程:读取配置文件-->解析配置-->创建Configuration对象-->将mybatis配置属性、mapper等信息封装到Configuration对象内-->以configuration作为参数创建sqlSessionFactory。
在本文中,将讲述SqlSession的结构、作用以及创建过程。在 MyBatis 中,SqlSession 是一个重要接口,它相当于一个门面,起着连接应用与底层执行器executor的作用。通过它,用户可以来实现对数据的操作、事务的控制和mapper代理对象的获取。在 MyBatis 中有两个SqlSession实现类,DefaultSqlSession 和 SqlSessionManager。本文重点讲DefaultSqlSession,并将捎带一点SqlSessionManager。
1.SqlSession的创建过程
public SqlSession openSession() {
return this.openSessionFromDataSource(this.configuration.getDefaultExecutorType(), (TransactionIsolationLevel)null, false);
}
/**
* 参数:execType:"SIMPLE", level: null, autoCommit: false
*/
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
Transaction tx = null;
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);
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;
}
openSessionFromDataSource在创建SqlSession过程中做了3件事情:创建事务, 创建执行器, 创建sqlSession。每一步的结果都作为下一步的参数,最终构建出一个可用来表示会话的sqlSession。事实上,sqlSession对象既不直接管理数据库的连接,也不直接操作数据,而是将功能交给了执行器--执行器负责doQuery,同时通过内部封装的tx对象来管理数据库连接和事务的提交/回滚。
- 创建事务工厂,用于创建事务,进行事务控制。做法很简单,若在配置文件中对environment配置了事务工厂,那么就从configuration的environment属性中获取transactionFactory,没有则新建一个ManagedTransactionFactory对象。然后由该工厂对象创建事务。
TransactionFactory transactionFactory = this.getTransactionFactoryFromEnvironment(environment);
tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
在mybatis中,事务的作用:获取连接、提交、回滚、关闭连接。
public interface Transaction {
Connection getConnection() throws SQLException;
void commit() throws SQLException;
void rollback() throws SQLException;
void close() throws SQLException;
Integer getTimeout() throws SQLException;
}
-
创建执行器Executor
Executor创建过程
Executor有3种类型: Simple, Reuse, Batch.
//todo:区别与共性
2.1 SimpleExecutor的创建
直接调用了父类BaseExecutor的构造方法。
SimpleExecutor的创建
2.2 创建成功之后,若启用了缓存,那么创建一个CachingExecutor并用其包装SimpleExecutor对象。
2.3 拦截器链为executor植入插件,使用插件完成对executor的代理。简单来说就是采用责任链模式,一层层的创建代理对象,最后返回终极版的executor代理对象。
public Object pluginAll(Object target) {
Interceptor interceptor;
for(Iterator var2 = this.interceptors.iterator(); var2.hasNext(); target = interceptor.plugin(target)) {
interceptor = (Interceptor)var2.next();
}
return target;
}
default Object plugin(Object target) {
return Plugin.wrap(target, this);
}
public static Object wrap(Object target, Interceptor interceptor) {
//获取方法签名
Map<Class<?>, Set<Method>> signatureMap = getSignatureMap(interceptor);
Class<?> type = target.getClass();
Class<?>[] interfaces = getAllInterfaces(type, signatureMap);
//创建代理对象
return interfaces.length > 0 ? Proxy.newProxyInstance(type.getClassLoader(), interfaces, new Plugin(target, interceptor, signatureMap)) : target;
}
- 创建SqlSession
public DefaultSqlSession(Configuration configuration, Executor executor, boolean autoCommit) {
this.configuration = configuration;
this.executor = executor;
this.dirty = false;
this.autoCommit = autoCommit;
}
还是属性封装,将SqlSessionFactory对象的Configuration、刚创建的executor、autoCommit三个属性封装到sqlSession对象中。
到这里,sqlSession对象就创建并初始化了。它内部的核心组件就是负责完成与数据库交互的executor和封装配置属性的Configuration。它的作用主要有:通过configuration获取到mapper、通过executor完成crud、事务管理和连接管理。
网友评论