Mybatis流程分析(三):构建SqlSession实现Mybatis的会话管理
本系列文章皆在从细节着手,由浅入深的分析Mybatis
框架内部的处理逻辑,带你从一个全新的角度来认识Mybatis
的工作原理。
思考,输出,沉淀。用通俗的语言陈述技术,让自己和他人都有所收获。 作者:毅航😜
前言
我们可以将 Configuration
理解为一个大管家
,其主要用于保存Mybatis
配置文件xml
中的配置信息;而SqlSessionFactory
则是一个SqlSession
的工厂,其主要作用构建SqlSession
对象。
本章我们便对SqlSessionFactory
构建的SqlSession
进行研究和分析。
通过工厂获取SqlSession
在之前分析中我们提到对于SqlSessionFactory
工厂而言,其会调用opeanSession
方法来获取一个SqlSession
对象信息。
具体来看,在Mybatis
内部其会首先构建一个DefaultSqlSessionFactory
对象,然后调用其内部的openSession
方法。更进一步,其会将构建SqlSession
的逻辑委托给DefaultSqlSessionFactory
中的openSessionFromDataSource
方法来完成。其内部代码逻辑如下所示:
DefaultSqlSessionFactory # openSessionFromDataSource
public SqlSession openSession() {
return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
}
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
Transaction tx = null;
// 获取mybatis.xml配置文件中的Environment的配置环境信息
final Environment environment = configuration.getEnvironment();
// 根据environment下的配置信息,构建一个事务管理器工厂
final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
// 通过通常构建一个事务管理器工厂
tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
// 构建Executor执行器
final Executor executor = configuration.newExecutor(tx, execType);
// 返回一个DefaultSqlSessionFactory
return new DefaultSqlSession(configuration, executor, autoCommit);
}
可以看到,openSessionFromDataSource
内部在构建SqlSession
时,需要三个成员
信息,其中:
Configuration
:Mybatis
全部的配置信息的对象
Executor
:Mybatis
的执行器autoCommit
: 一个Boolean
类型变量,默认传入为false
。
进一步,Mybatis
内部获取SqlSession
对象的整个流程调用关系可总结为下图所示内容:
(注:Executor
后续会单独一章进行分析,此处只需了解)
SqlSession
相关内容
分析完SqlSession
的构建后,我们再来看看这个SqlSession
到底会完成哪些功能
。
事实上,SqlSession
与SqlSessionFactory
一样其也为一个接口。其内部定义的方法如下所示:
SqlSession
接口
public interface SqlSession extends Closeable {
<T> T selectOne(String statement);
<T> T selectOne(String statement, Object parameter);
<E> List<E> selectList(String statement);
// .... 省略其他方法,如:selectxx、insert、update、delete、commit、rollback等
我们注意到SqlSession
内部除了定义一些selectxxx
方法,还会包含一些insert、update、delete
方法。而这些方法入参
为一个String
字符串信息。
虽然目前我们并不知道这些方法的相关作用,但是通过对方法名的分析,我们有理由猜测其可能同数据库相关有所关系。有这样猜测的原因主要出于以下几点:
-
首先,在操纵数据库的
DML
语言完成对数据库的操纵时,我们所写的sql
通常都为select、insert、update
。在结合Mybatis
作为一款同数据库交互的框架来看,我们完全有理由猜测此处的方法信息可能与数据库的交互有关。 -
其次,我们以其中
selectOne
为例来看,其入参为一个名为statement
字符串。熟悉jdbc
开发者应该知道,在操纵数据库我们通常会构建一个Statement
对象,用以执行执行sql
语句,并返回结果对象。而框架中对于变量信息的命名通常都会做到见名知意
,所以此处传入的信息很可能为sql
语句。
结合上述两点,我们得出分析得出SqlSession
中定义的方法很可能与sql
执行息息相关。
接下来,我们便进入到SqlSession
的具体实现类DefaultSqlSession
中,看看该方法实现的逻辑是否如我们猜想的那样。
默认实现:DefaultSqlSession
DefaultSqlSession
的代码信息如下所示:
public class DefaultSqlSession implements SqlSession {
private final Configuration configuration;
private final Executor executor;
@Override
public <T> T selectOne(String statement,
Object parameter) {
// Popular vote was to return null on 0 results and throw exception on too many.
List<T> list = this.selectList(statement, parameter);
}
public <E> List<E> selectList(String statement,
Object parameter, RowBounds rowBounds) {
MappedStatement ms = configuration.getMappedStatement(statement);
// 交给执行器执行
return executor.query(ms, wrapCollection(parameter),
}
// .....省略其他方法实现
}
我们注意到,SqlSession
内部会持有Configuration、Executor
对象,并且在构建一个DefaultSqlSession
时必须将这些对象传入构造器,否则将无法创建DefaultSqlSession
对象。
而前面我们在构建SqlSession
中提到过,其在构建时会传入Configuration、Executor
等信息。相信看到这里,你对于DefaultSqlSession
构建的理解肯定会更加深刻。这些传入的对象的信息,统统都被被设定为SqlSession
的成员变量。
此外,我们注意到其中的SelectList
方法在实现时,会将执行逻辑委托于Executor
中的query
方法执行。
而在 MyBatis
中,执行器Executor
是一个关键的组件,它的作用是管理 SQL
语句的执行过程。进一步,MyBatis
使用 Executor
来协调数据库的访问,以及将 SQL
语句映射到对应的数据库操作。Executor
在 MyBatis
中起到了桥梁的作用,连接了应用程序和数据库之间的交互。
进一步,Executor
的主要作用总结为如下过程:
SQL
语句的执行 :Executor
负责将MyBatis
的映射文件中定义的SQL
语句转化为实际的数据库操作,例如查询、插入、更新、删除
等。- 缓存管理:
Executor
在执行SQL
语句时,会参与MyBatis
的缓存机制。根据缓存配置,Executor
可以从缓存中获取已经缓存的结果,避免不必要的数据库访问。 - 结果处理:
Executor
将数据库返回的结果转化为Java
对象,以供应用程序使用。这可以包括将结果映射到对应的实体对象或集合中。 - 事务管理:
Executor
参与MyBatis
的事务管理,确保一系列操作要么全部成功要么全部失败,保证数据的一致性。
总之,Executor
在 MyBatis
中扮演着重要的角色,负责处理数据库访问的各个方面,从而实现高效、可靠的数据库操作。
至此,我们之前对于SqlSession
的猜测基本基本得到了验证。事实上,在 MyBatis
中,SqlSession
是一个用于执行 SQL
操作的核心接口。它提供了与数据库的交互方法,可以执行查询、插入、更新、删除
等操作。
总结
至此,我们以如下的几行简单代码为例:
//<1> 加载配置文件
InputStream is = Resources.getResourceAsStream("mybatis.xml");
//<2> 创建sessionFactory对象
sessionFactory = new SqlSessionFactoryBuilder().build(is);
//<3> 获取sqlSession对象信息
SqlSession session = factoy.openSqlSession()
先后分析了SqlSessionFactory
和SqlSession
的相关内容。事实上,这其实背后的逻辑很简单。总结来看就是首先new
一个DefaultSqlSessionFactory
对象,然后通过该对象返回一个DefaultSqlSession
对象。此外,这个后续sql
语句都会委托于这个DefaultSqlSession
进行执行。大致逻辑如下所示:
当然,Mybatis
中执行Sql
的故事还在继续,后续我们将继续不断深入分析探究,让你还一种视角重新认为Mybatis
。
转载自:https://juejin.cn/post/7269070543881175075