Mybatis源码分析之SqlSession和Excutor(二)
通过上一篇文章的分析我们,我初步了解了它是如何创建sessionFactory的(地址:Mybatis源码分析之SqlSessionFactory(一)),
今天我们分析下Mybatis如何创建SqlSession( sessionFactory.openSession())和Excutor到底做了什么事情
还是上篇的代码demo
public static void main(String[] args) throws Exception {
SqlSessionFactory sessionFactory = null;
String resource = "configuration.xml";
sessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsReader(resource));
SqlSession sqlSession = sessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
System.out.println(userMapper.findUserById(1));
}
1:openSessionFromDataSource
通过openSession()最终调用的是 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();
}
}
说明:ExecutorType(执行器类型)类型有 SIMPLE(默认),REUSE,BATCH,
TransactionIsolationLevel 隔离级别5种
NONE(Connection.TRANSACTION_NONE),
READ_COMMITTED(Connection.TRANSACTION_READ_COMMITTED),
READ_UNCOMMITTED(Connection.TRANSACTION_READ_UNCOMMITTED),
REPEATABLE_READ(Connection.TRANSACTION_REPEATABLE_READ),
SERIALIZABLE(Connection.TRANSACTION_SERIALIZABLE);
通过源码看出首先是从configuration获取environment,接着创建Transaction,
最后通过 configuration.newExecutor创建Executor。
public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
executorType = executorType == null ? defaultExecutorType : executorType;
executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
Executor executor;
//根据executorType创建不同的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 (cacheEnabled) {
executor = new CachingExecutor(executor);
}
executor = (Executor) interceptorChain.pluginAll(executor);
return executor;
}
根据executorType创建对应的Executor,从源码可以看出他有BatchExecutor、ReuseExecutor、CachingExecutor、SimpleExecutor
那么Executor是做什么的呢?
2:Executor
Executor是接口,是对于Statement的封装,我们看下Executor,他是真正执行sql的地方。
public interface Executor {
ResultHandler NO_RESULT_HANDLER = null;
int update(MappedStatement ms, Object parameter) throws SQLException;
List query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey cacheKey, BoundSql boundSql) throws SQLException;
List query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException;
Cursor queryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds) throws SQLException;
List flushStatements() throws SQLException;
void commit(boolean required) throws SQLException;
void rollback(boolean required) throws SQLException;
CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql);
boolean isCached(MappedStatement ms, CacheKey key);
void clearLocalCache();
void deferLoad(MappedStatement ms, MetaObject resultObject, String property, CacheKey key, Class targetType);
Transaction getTransaction();
void close(boolean forceRollback);
boolean isClosed();
void setExecutorWrapper(Executor executor);
}
上面源码我可以看到Executor接口定义了update 、query、commit、rollback等方法,他的实现类如下图

我们拿其中的SimpleExecutor类里面的doQuery方法看下源码
@Override
public List doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
Statement stmt = null;
try {
Configuration configuration = ms.getConfiguration();
StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
//StatementHandler封装了Statement, 让 StatementHandler 去处理
stmt = prepareStatement(handler, ms.getStatementLog());
return handler.query(stmt, resultHandler);
} finally {
closeStatement(stmt);
}
}
我们看看StatementHandler 的一个实现类 PreparedStatementHandler(这也是我们最常用的,封装的是PreparedStatement), 看看它使怎么去处理的:
@Override
public List query(Statement statement, ResultHandler resultHandler) throws SQLException {
String sql = boundSql.getSql();
//这个和jdbc一样执行sql
statement.execute(sql);
//结果交给了ResultSetHandler 去处理
return resultSetHandler.handleResultSets(statement);
}
以上是sql底层执行的基本流程,说的直白一点就是所以sql底层都交给了Excutor,我们将在下一讲中分析上一层的调用,也就是Excutor的上层。
我们继续回到openSessionFromDataSource上面来,通过上面的executor的创建最终是创建
new DefaultSqlSession(configuration, executor, autoCommit);到此我们已经完成了SqlSession的创建,后面我们将分析sqlSession.getMapper 也就是Excutor的上层调用。
Mybatis源码分析之SqlSession和Excutor(二)的更多相关文章
- 精尽MyBatis源码分析 - SQL执行过程(二)之 StatementHandler
该系列文档是本人在学习 Mybatis 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释(Mybatis源码分析 GitHub 地址.Mybatis-Spring 源码分析 GitHub ...
- 精尽 MyBatis 源码分析 - SqlSession 会话与 SQL 执行入口
该系列文档是本人在学习 Mybatis 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释(Mybatis源码分析 GitHub 地址.Mybatis-Spring 源码分析 GitHub ...
- MyBatis 源码分析
MyBatis 运行过程 传统的 JDBC 编程查询数据库的代码和过程总结. 加载驱动. 创建连接,Connection 对象. 根据 Connection 创建 Statement 或者 Prepa ...
- MyBatis源码分析-MyBatis初始化流程
MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以对配置和原生Map使用简 ...
- MyBatis源码分析-SQL语句执行的完整流程
MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以对配置和原生Map使用简 ...
- MyBatis源码分析(4)—— Cache构建以及应用
@(MyBatis)[Cache] MyBatis源码分析--Cache构建以及应用 SqlSession使用缓存流程 如果开启了二级缓存,而Executor会使用CachingExecutor来装饰 ...
- MyBatis源码分析(2)—— Plugin原理
@(MyBatis)[Plugin] MyBatis源码分析--Plugin原理 Plugin原理 Plugin的实现采用了Java的动态代理,应用了责任链设计模式 InterceptorChain ...
- 【MyBatis源码分析】select源码分析及小结
示例代码 之前的文章说过,对于MyBatis来说insert.update.delete是一组的,因为对于MyBatis来说它们都是update:select是一组的,因为对于MyBatis来说它就是 ...
- MyBatis源码分析之环境准备篇
前言 之前一段时间写了[Spring源码分析]系列的文章,感觉对Spring的原理及使用各方面都掌握了不少,趁热打铁,开始下一个系列的文章[MyBatis源码分析],在[MyBatis源码分析]文章的 ...
随机推荐
- MyEclipse10安装Log4E插件
一. Log4E插件下载 下载地址:http://log4e.jayefem.de/content/view/3/2/ 二.安装Log4E插件 将下载下来的压缩包解压缩,如下图所示: 解压缩生成的[d ...
- 在ASP.NET MVC中实现本地化和全球化
在开发多语言网站时,我们可以为某种语言创建一个资源文件,根据浏览器所设置的不同语言偏好,让运行时选择具体使用哪个资源文件.资源文件在生成程序集的时候被嵌入到程序集. 本篇体验,在ASP.NET MVC ...
- UIProgressView 详解
自定义progressView 包括背景图片和进度条的图片以及进度条的高度. //进度条 UIProgressView *aProgressView = [[UIProgressView allo ...
- C#编程(四十四)----------string和stringbuilder
System.String类 首先string类是静态的,System.String是最常用的字符串操作类,可以帮助开发者完成绝大部分的字符串操作功能,使用方便. 1.比较字符串 比较字符串是指按照字 ...
- Linux 用户和用户操作
1,创建组 groupadd test 增加一个test组 2,修改组 groupmod -n test2 test 将test组的名子改成test2 3,删除组 groupdel test2 删除 ...
- Kettle优化就这么多
版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/ClamReason/article/details/49930479 Kettle正常转换速度 场景 ...
- Material Designer的低版本兼容实现(八)—— Flat Button
除了中规中矩的矩形按钮外,5.0中将按钮扁平化,产生了一个扁平按钮——Flat Button.这个按钮降低了很多存在感,主要用于在对话框,提示栏中.让整个界面减少层级.今天说的就是它的用法. 这 ...
- ScrollView滚动条的各种设置
ScrollView滚动条不显示:android:scrollbars="none"ScrollView滚动条恒显示:android:fadeScrollbars="fa ...
- [Android Pro] 开发一流的 Android SDK:Fabric SDK 的创建经验
cp from : https://academy.realm.io/cn/posts/oredev-ty-smith-building-android-sdks-fabric/ Ty Smith T ...
- Java和C#差异点
语法:----------------------------------------------------------1. Java的byte为-128~127相当于c#的sbyte,c#byte ...