当前位置: 首页 > ds >正文

手写MyBatis第31弹-用工厂模式重构MyBatis的SqlSession创建过程

🥂(❁´◡`❁)您的点赞👍➕评论📝➕收藏⭐是作者创作的最大动力🤞

💖📕🎉🔥 支持我:点赞👍+收藏⭐️+留言📝欢迎留言讨论

🔥🔥🔥(源码 + 调试运行 + 问题答疑)

🔥🔥🔥  有兴趣可以联系我。

我们常常在当下感到时间慢,觉得未来遥远,但一旦回头看,时间已经悄然流逝。对于未来,尽管如此,也应该保持一种从容的态度,相信未来仍有许多可能性等待着我们。 

  1. MyBatis核心工厂揭秘:SqlSessionFactory如何打造高效的数据库会话生产线

  2. 设计模式之美:用工厂模式重构MyBatis的SqlSession创建过程

  3. 深入MyBatis源码:解析SqlSessionFactory的重量级身份与创建逻辑

  4. 手写MyBatis工厂层:打造可配置化的SqlSession生产体系

  5. 架构师视角:为什么SqlSessionFactory是MyBatis中最重量级的组件?


正文

在前两篇文章中,我们实现了SqlSession的CRUD方法并重构了MapperProxy,建立了清晰的执行链路。然而,一个关键问题尚未解决:SqlSession实例应该如何被创建和管理?今天,我们将引入MyBatis架构中的另一个核心组件——SqlSessionFactory,通过工厂模式来优雅地解决这个问题。

一、为何需要SqlSessionFactory:创建逻辑的封装与复用

直接使用new DefaultSqlSession(configuration, executor)来创建会话虽然可行,但存在诸多问题:

  1. 创建逻辑复杂:一个完整的SqlSession创建需要组装ConfigurationExecutor以及可能的事务管理器和连接对象,这些细节不应该暴露给客户端代码。

  2. 配置一致性:确保所有SqlSession实例使用相同的配置基础,避免因配置不一致导致的难以排查的问题。

  3. 资源管理:集中管理Executor的创建和配置,便于实现执行器类型的可配置化。

  4. 扩展性:为未来支持不同类型的SqlSession(如批处理会话、管理型会话)预留扩展点。

工厂模式正是解决这些问题的利器。它通过提供一个专门的工厂类来封装对象的创建逻辑,让客户端无需关心具体的创建细节。

二、SqlSessionFactory的架构设计与实现

让我们通过一个架构图来全面了解SqlSessionFactory在整体框架中的位置和作用:

从上图可以看出,SqlSessionFactory作为整个框架的配置中心和生产中心,处于承上启下的关键位置。

第一步:定义SqlSessionFactory接口

public interface SqlSessionFactory {/*** 打开一个SqlSession,使用默认的配置*/SqlSession openSession();/*** 指定是否自动提交事务*/SqlSession openSession(boolean autoCommit);/*** 指定连接对象,用于与现有事务集成*/SqlSession openSession(Connection connection);/*** 指定事务隔离级别*/SqlSession openSession(TransactionIsolationLevel level);/*** 获取配置信息*/Configuration getConfiguration();}

第二步:实现DefaultSqlSessionFactory

 public class DefaultSqlSessionFactory implements SqlSessionFactory {private final Configuration configuration;public DefaultSqlSessionFactory(Configuration configuration) {this.configuration = configuration;}@Overridepublic SqlSession openSession() {return openSession(false); // 默认非自动提交}@Overridepublic 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);// 创建SqlSessionreturn new DefaultSqlSession(configuration, executor);} catch (Exception e) {// 关闭事务如果创建失败if (tx != null) {tx.close();}throw new RuntimeException("Error opening session. Cause: " + e);}}@Overridepublic SqlSession openSession(Connection connection) {// 基于现有连接创建事务和执行器Transaction tx = new ManagedTransaction(connection);Executor executor = new SimpleExecutor(configuration, tx);return new DefaultSqlSession(configuration, executor);}@Overridepublic SqlSession openSession(TransactionIsolationLevel level) {// 实现略:创建指定隔离级别的事务return openSession(false);}@Overridepublic Configuration getConfiguration() {return configuration;}}
三、为什么SqlSessionFactory是重量级的?

从上面的实现可以看出,SqlSessionFactory的重量级体现在以下几个方面:

  1. 配置信息承载者:它持有Configuration对象,这个对象包含了MyBatis运行所需的所有配置信息:数据源、映射器、类型处理器、插件等。这些配置在应用生命周期内通常不会改变。

  2. 资源初始化成本高Configuration的初始化过程需要解析XML配置、扫描注解、注册映射器等,这些都是相对耗时的操作。

  3. 线程安全要求:作为共享组件,SqlSessionFactory必须是线程安全的,这增加了其实现的复杂性。

  4. 长生命周期:通常一个应用对应一个SqlSessionFactory实例,伴随应用的整个生命周期。

正因为这些特性,我们应该将SqlSessionFactory设计为单例,在应用启动时创建,在整个运行期间重复使用。

四、Executor的类型配置与选择

Executor是MyBatis执行SQL的核心组件,不同的执行器类型适应不同的场景:

 public enum ExecutorType {SIMPLE,    // 简单执行器:每次执行都会创建新的PreparedStatementREUSE,     // 复用执行器:复用PreparedStatementBATCH      // 批处理执行器:批量执行更新操作}

SqlSessionFactory中,我们可以通过配置来决定创建哪种类型的执行器:

 // 在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的构建:

 public class SqlSessionFactoryBuilder {public SqlSessionFactory build(Configuration configuration) {return new DefaultSqlSessionFactory(configuration);}public SqlSessionFactory build(InputStream inputStream) {// 解析XML配置,构建Configuration,然后创建SqlSessionFactoryXMLConfigBuilder parser = new XMLConfigBuilder(inputStream);Configuration config = parser.parse();return build(config);}public SqlSessionFactory build(Reader reader) {// 类似上面,从Reader读取配置// ...}}

这种构建者模式的优势在于:

  1. 分离配置解析与工厂创建:让每个类职责更加单一

  2. 支持多种配置源:可以支持XML、Properties、编程式配置等多种方式

  3. 灵活的构建过程:可以在构建过程中添加验证、优化等逻辑

六、总结与最佳实践

通过引入SqlSessionFactory,我们完成了MyBatis核心架构的又一个重要模块。工厂模式的应用让我们的框架更加专业和灵活:

  1. 创建逻辑封装:将复杂的SqlSession创建过程封装在工厂中,客户端代码更加简洁

  2. 配置集中管理:通过SqlSessionFactory统一管理所有配置,确保一致性

  3. 灵活的会话控制:支持创建具有不同特性的SqlSession实例

  4. 更好的资源管理:集中管理Executor的创建和生命周期

在实际应用中,我们应该遵循以下最佳实践:

  • SqlSessionFactory作为应用级单例管理

  • 根据具体场景选择合适的ExecutorType(批处理操作使用BATCH,高并发查询考虑REUSE

  • 通过SqlSessionFactoryBuilder统一构建工厂实例,确保配置的一致性

下次当你使用MyBatis时,不妨思考一下:每一个简单的getMapper()调用背后,是整个工厂体系在默默支撑。这种精妙的分层设计和职责划分,正是优秀框架的迷人之处。


💖学习知识需费心,
📕整理归纳更费神。
🎉源码免费人人喜,
🔥码农福利等你领!

💖常来我家多看看,
📕我是程序员扣棣,
🎉感谢支持常陪伴,
🔥点赞关注别忘记!

💖山高路远坑又深,
📕大军纵横任驰奔,
🎉谁敢横刀立马行?
🔥唯有点赞+关注成!

http://www.xdnf.cn/news/18823.html

相关文章:

  • 数据可视化——matplotlib库
  • Rust Web开发指南 第三章(Axum 请求体解析:处理 JSON、表单与文件上传)
  • IQC、IPQC、PQC、FQC、OQC在ERP/MES/WMS中的系统协同
  • [每周一更]-(第157期):深入理解Go语言的垃圾回收机制:调优与监控
  • C++ 容器——vector
  • 第2章:幽灵协议初现
  • 通过API接口多并发采集数据的方法与实践
  • 马斯克宣布开源Grok 2.5:非商业许可引争议,模型需8×40GB GPU运行,Grok 3半年后开源
  • 新的 Gmail 网络钓鱼攻击利用 AI 提示注入来逃避检测
  • VScode设置鼠标滚轮调节代码
  • 深度学习部署实战 Ubuntu24.04单机多卡部署ERNIE-4.5-VL-28B-A3B-Paddle文心多模态大模型(详细教程)
  • LeetCode-542. 01 矩阵
  • 数据库的基本操作
  • 16、web应用系统分析语设计
  • 构建AI智能体:十二、给词语绘制地图:Embedding如何构建机器的认知空间
  • 基于Langchain框架的DeepSeek-v3+Faiss实现RAG知识问答系统(含完整代码)
  • 华为云Stack环境中计算资源,存储资源,网络资源发放前的准备工作(上篇)
  • wpf之Grid控件
  • 鸿蒙分布式计算实战:用 ArkTS+Worker 池落地可运行任务管理 Demo,从单设备到跨设备全方案
  • 07-分布式能力与多设备协同
  • JDBC入门
  • DAY 55 序列预测任务介绍
  • 小红书自动评论插件
  • JUC之并发容器
  • 深度学习与自动驾驶中的一些技术
  • Java基础(十四)分布式
  • KingBase数据库迁移利器:KDTS工具深度解析与实战指南
  • golang6 条件循环
  • 01-鸿蒙系统概览与发展历程
  • Android面试指南(五)