MyBatis源码解析系列之二:深入理解SqlSessionFactory和SqlSession
欢迎大家回到我的MyBatis源码解析系列。在上一期中,我们初步了解了MyBatis的整体架构和核心组件。这篇文章将深入解析 SqlSessionFactory
和 SqlSession
的源码,帮助大家更好地理解它们的实现原理。
一、SqlSessionFactory的创建过程
SqlSessionFactory
是MyBatis的核心工厂类,用于创建 SqlSession
实例。SqlSessionFactory
的创建过程通常分为以下几个步骤:
- 读取配置文件
- 解析配置文件
- 创建Configuration对象
- 构建SqlSessionFactory实例
我们以 SqlSessionFactoryBuilder
类为例,来看一下具体的创建过程。
1. 读取配置文件
配置文件通常是一个XML文件,包含了数据库连接信息、映射文件等。SqlSessionFactoryBuilder
会读取该文件并构建一个 InputStream
。
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
2. 解析配置文件
SqlSessionFactoryBuilder
使用 XMLConfigBuilder
类来解析XML配置文件。XMLConfigBuilder
会解析XML文件中的各个节点,并将解析结果存储在 Configuration
对象中。
public SqlSessionFactory build(InputStream inputStream) {
return build(inputStream, null, null);
}
public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
try {
XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
Configuration config = parser.parse();
return build(config);
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error building SqlSession.", e);
} finally {
ErrorContext.instance().reset();
try {
inputStream.close();
} catch (IOException e) {
// Intentionally ignore. Prefer previous error.
}
}
}
3. 创建Configuration对象
XMLConfigBuilder
解析XML文件后,会创建并初始化一个 Configuration
对象,该对象包含了MyBatis的所有配置信息。
public Configuration parse() {
if (parsed) {
throw new BuilderException("Each XMLConfigBuilder can only be used once.");
}
parsed = true;
parseConfiguration(parser.evalNode("/configuration"));
return configuration;
}
private void parseConfiguration(XNode root) {
try {
propertiesElement(root.evalNode("properties"));
Properties settings = settingsAsProperties(root.evalNode("settings"));
loadCustomVfs(settings);
typeAliasesElement(root.evalNode("typeAliases"));
pluginElement(root.evalNode("plugins"));
objectFactoryElement(root.evalNode("objectFactory"));
objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
reflectorFactoryElement(root.evalNode("reflectorFactory"));
settingsElement(settings);
environmentsElement(root.evalNode("environments"));
databaseIdProviderElement(root.evalNode("databaseIdProvider"));
typeHandlerElement(root.evalNode("typeHandlers"));
mapperElement(root.evalNode("mappers"));
} catch (Exception e) {
throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
}
}
4. 构建SqlSessionFactory实例
最后,SqlSessionFactoryBuilder
使用 Configuration
对象来构建一个 DefaultSqlSessionFactory
实例。
public SqlSessionFactory build(Configuration config) {
return new DefaultSqlSessionFactory(config);
}
二、SqlSession的创建与使用
SqlSession
是MyBatis中用于执行SQL语句和管理事务的核心接口。SqlSession
的创建通常由 SqlSessionFactory
完成。
1. 创建SqlSession
SqlSessionFactory
提供了多种创建 SqlSession
的方法,最常用的是 openSession()
方法。
public SqlSession openSession() {
return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
}
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();
}
}
2. 使用SqlSession
SqlSession
提供了一系列执行SQL语句的方法,如 selectOne
、selectList
、insert
、update
和 delete
。这些方法内部会通过 Executor
来执行具体的SQL语句。
try (SqlSession session = sqlSessionFactory.openSession()) {
Blog blog = session.selectOne("org.mybatis.example.BlogMapper.selectBlog", 101);
}
三、总结
在本篇文章中,我们深入解析了 SqlSessionFactory
和 SqlSession
的创建与使用过程。通过源码的解析,相信大家对MyBatis的核心组件有了更深入的理解。下一篇文章中,我们将进一步探讨 Executor
和 MappedStatement
的内部实现原理,敬请期待。
希望大家继续关注我的系列文章,点赞、收藏和分享就是对我最大的支持。如果有任何问题或建议,欢迎在评论区留言讨论。
如需获取更多MyBatis源码解析的详细内容,请持续关注我的CSDN博客,更多精彩内容等着你!