🥂(❁´◡`❁)您的点赞👍➕评论📝➕收藏⭐是作者创作的最大动力🤞
💖📕🎉🔥 支持我:点赞👍+收藏⭐️+留言📝欢迎留言讨论
🔥🔥🔥(源码 + 调试运行 + 问题答疑)
🔥🔥🔥 有兴趣可以联系我。
我们常常在当下感到时间慢,觉得未来遥远,但一旦回头看,时间已经悄然流逝。对于未来,尽管如此,也应该保持一种从容的态度,相信未来仍有许多可能性等待着我们。
-
MyBatis核心工厂揭秘:SqlSessionFactory如何打造高效的数据库会话生产线
-
设计模式之美:用工厂模式重构MyBatis的SqlSession创建过程
-
深入MyBatis源码:解析SqlSessionFactory的重量级身份与创建逻辑
-
手写MyBatis工厂层:打造可配置化的SqlSession生产体系
-
架构师视角:为什么SqlSessionFactory是MyBatis中最重量级的组件?
正文
在前两篇文章中,我们实现了SqlSession
的CRUD方法并重构了MapperProxy
,建立了清晰的执行链路。然而,一个关键问题尚未解决:SqlSession
实例应该如何被创建和管理?今天,我们将引入MyBatis架构中的另一个核心组件------SqlSessionFactory
,通过工厂模式来优雅地解决这个问题。
一、为何需要SqlSessionFactory:创建逻辑的封装与复用
直接使用new DefaultSqlSession(configuration, executor)
来创建会话虽然可行,但存在诸多问题:
-
创建逻辑复杂 :一个完整的
SqlSession
创建需要组装Configuration
、Executor
以及可能的事务管理器和连接对象,这些细节不应该暴露给客户端代码。 -
配置一致性 :确保所有
SqlSession
实例使用相同的配置基础,避免因配置不一致导致的难以排查的问题。 -
资源管理 :集中管理
Executor
的创建和配置,便于实现执行器类型的可配置化。 -
扩展性 :为未来支持不同类型的
SqlSession
(如批处理会话、管理型会话)预留扩展点。
工厂模式正是解决这些问题的利器。它通过提供一个专门的工厂类来封装对象的创建逻辑,让客户端无需关心具体的创建细节。
二、SqlSessionFactory的架构设计与实现
让我们通过一个架构图来全面了解SqlSessionFactory
在整体框架中的位置和作用:

从上图可以看出,SqlSessionFactory
作为整个框架的配置中心和生产中心,处于承上启下的关键位置。
第一步:定义SqlSessionFactory接口
java
public interface SqlSessionFactory {
/**
* 打开一个SqlSession,使用默认的配置
*/
SqlSession openSession();
/**
* 指定是否自动提交事务
*/
SqlSession openSession(boolean autoCommit);
/**
* 指定连接对象,用于与现有事务集成
*/
SqlSession openSession(Connection connection);
/**
* 指定事务隔离级别
*/
SqlSession openSession(TransactionIsolationLevel level);
/**
* 获取配置信息
*/
Configuration getConfiguration();
}
第二步:实现DefaultSqlSessionFactory
java
public class DefaultSqlSessionFactory implements SqlSessionFactory {
private final Configuration configuration;
public DefaultSqlSessionFactory(Configuration configuration) {
this.configuration = configuration;
}
@Override
public SqlSession openSession() {
return openSession(false); // 默认非自动提交
}
@Override
public SqlSession openSession(boolean autoCommit) {
// 创建事务
Transaction tx = null;
try {
Environment environment = configuration.getEnvironment();
TransactionFactory transactionFactory = environment.getTransactionFactory();
tx = transactionFactory.newTransaction(environment.getDataSource(), autoCommit);
// 创建执行器
Executor executor = new SimpleExecutor(configuration, tx);
// 创建SqlSession
return new DefaultSqlSession(configuration, executor);
} catch (Exception e) {
// 关闭事务如果创建失败
if (tx != null) {
tx.close();
}
throw new RuntimeException("Error opening session. Cause: " + e);
}
}
@Override
public SqlSession openSession(Connection connection) {
// 基于现有连接创建事务和执行器
Transaction tx = new ManagedTransaction(connection);
Executor executor = new SimpleExecutor(configuration, tx);
return new DefaultSqlSession(configuration, executor);
}
@Override
public SqlSession openSession(TransactionIsolationLevel level) {
// 实现略:创建指定隔离级别的事务
return openSession(false);
}
@Override
public Configuration getConfiguration() {
return configuration;
}
}
三、为什么SqlSessionFactory是重量级的?
从上面的实现可以看出,SqlSessionFactory
的重量级体现在以下几个方面:
-
配置信息承载者 :它持有
Configuration
对象,这个对象包含了MyBatis运行所需的所有配置信息:数据源、映射器、类型处理器、插件等。这些配置在应用生命周期内通常不会改变。 -
资源初始化成本高 :
Configuration
的初始化过程需要解析XML配置、扫描注解、注册映射器等,这些都是相对耗时的操作。 -
线程安全要求 :作为共享组件,
SqlSessionFactory
必须是线程安全的,这增加了其实现的复杂性。 -
长生命周期 :通常一个应用对应一个
SqlSessionFactory
实例,伴随应用的整个生命周期。
正因为这些特性,我们应该将SqlSessionFactory
设计为单例,在应用启动时创建,在整个运行期间重复使用。
四、Executor的类型配置与选择
Executor
是MyBatis执行SQL的核心组件,不同的执行器类型适应不同的场景:
java
public enum ExecutorType {
SIMPLE, // 简单执行器:每次执行都会创建新的PreparedStatement
REUSE, // 复用执行器:复用PreparedStatement
BATCH // 批处理执行器:批量执行更新操作
}
在SqlSessionFactory
中,我们可以通过配置来决定创建哪种类型的执行器:
java
// 在openSession方法中根据配置创建不同类型的执行器
Executor executor;
if (ExecutorType.BATCH == configuration.getDefaultExecutorType()) {
executor = new BatchExecutor(configuration, tx);
} else if (ExecutorType.REUSE == configuration.getDefaultExecutorType()) {
executor = new ReuseExecutor(configuration, tx);
} else {
executor = new SimpleExecutor(configuration, tx);
}
// 还可以支持在openSession时指定执行器类型
public SqlSession openSession(ExecutorType execType) {
Transaction tx = createTransaction();
Executor executor = createExecutor(tx, execType);
return new DefaultSqlSession(configuration, executor);
}
五、SqlSessionFactory的构建者:SqlSessionFactoryBuilder
为了进一步分离关注点,我们引入SqlSessionFactoryBuilder
来专门负责SqlSessionFactory
的构建:
java
public class SqlSessionFactoryBuilder {
public SqlSessionFactory build(Configuration configuration) {
return new DefaultSqlSessionFactory(configuration);
}
public SqlSessionFactory build(InputStream inputStream) {
// 解析XML配置,构建Configuration,然后创建SqlSessionFactory
XMLConfigBuilder parser = new XMLConfigBuilder(inputStream);
Configuration config = parser.parse();
return build(config);
}
public SqlSessionFactory build(Reader reader) {
// 类似上面,从Reader读取配置
// ...
}
}
这种构建者模式的优势在于:
-
分离配置解析与工厂创建:让每个类职责更加单一
-
支持多种配置源:可以支持XML、Properties、编程式配置等多种方式
-
灵活的构建过程:可以在构建过程中添加验证、优化等逻辑
六、总结与最佳实践
通过引入SqlSessionFactory
,我们完成了MyBatis核心架构的又一个重要模块。工厂模式的应用让我们的框架更加专业和灵活:
-
创建逻辑封装 :将复杂的
SqlSession
创建过程封装在工厂中,客户端代码更加简洁 -
配置集中管理 :通过
SqlSessionFactory
统一管理所有配置,确保一致性 -
灵活的会话控制 :支持创建具有不同特性的
SqlSession
实例 -
更好的资源管理 :集中管理
Executor
的创建和生命周期
在实际应用中,我们应该遵循以下最佳实践:
-
将
SqlSessionFactory
作为应用级单例管理 -
根据具体场景选择合适的
ExecutorType
(批处理操作使用BATCH
,高并发查询考虑REUSE
) -
通过
SqlSessionFactoryBuilder
统一构建工厂实例,确保配置的一致性
下次当你使用MyBatis时,不妨思考一下:每一个简单的getMapper()
调用背后,是整个工厂体系在默默支撑。这种精妙的分层设计和职责划分,正是优秀框架的迷人之处。
💖学习知识需费心,
📕整理归纳更费神。
🎉源码免费人人喜,
🔥码农福利等你领!💖常来我家多看看,
📕我是程序员扣棣,
🎉感谢支持常陪伴,
🔥点赞关注别忘记!💖山高路远坑又深,
📕大军纵横任驰奔,
🎉谁敢横刀立马行?
🔥唯有点赞+关注成!