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

手写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.dtcms.com/a/348102.html

相关文章:

  • 小迪安全v2023学习笔记(七十一讲)—— Python安全反序列化反编译格式化字符串安全
  • 深入解析MyBatis中#{}和${}的区别与应用场景
  • Implementing Redis in C++ : E(AVL树详解)
  • spring源码之事务篇(事务管理器整个流程)
  • 笔记 | Anaconda卸载重装
  • Hyperledger Fabric官方中文教程-改进笔记(十五)-从通道中删除组织
  • 【机器学习】3 Generative models for discrete data
  • HTML网页游戏五子棋
  • 电路学习(四)二极管
  • Spring框架相关面试题
  • 【机器学习】4 Gaussian models
  • 【网络运维】Shell 脚本编程:while 循环与 until 循环
  • Python自学笔记11 Numpy的索引和切片
  • Shell脚本-expect
  • VirtualBox安装openEuler24.03
  • 【C++】函数返回方式详解:传值、传引用与传地址
  • 校园跑腿小程序源码 | 跑腿便利店小程序 含搭建教程
  • 如何在 Ubuntu 上安装和配置 Samba ?
  • 2025年渗透测试面试题总结-30(题目+回答)
  • Java 20 新特性及具体应用
  • Cisdem Video Converter for mac 优秀的视频格式转换工具
  • 夜间跌倒检测响应速度↑150%!陌讯多模态骨架追踪算法在智慧养老院的落地实践
  • 埃氏筛|树dfs|差分计数
  • JVM OOM问题排查与解决思路
  • Meta AI 剧变:汪滔挥刀重组,Llama 开源路线告急,超级智能梦碎还是重生?
  • 96、23种设计模式之原型模式(5/23)
  • STM32 USB 之大坑
  • ubuntu中网卡的 IP 及网关配置设置为永久生效
  • Ubuntu24.04环境下causal_conv1d和mamba_ssm安装
  • 嵌入式八股文面试题总结(QT、RTOS、Linux、ARM、C/C++)(持续更新)