MyBatis SqlSession 是如何创建的? 它与 SqlSessionFactory 有什么关系?

devtools/2025/3/18 17:13:16/

SqlSession 是 MyBatis 中与数据库交互的核心接口,它提供了执行 SQL 语句、管理事务、获取 Mapper 接口代理对象等关键功能。 SqlSession 实例 不是直接通过 new 关键字创建的,而是通过 SqlSessionFactory 工厂来创建的。 SqlSessionFactory 负责创建 SqlSession 实例,并管理 SqlSession 的生命周期。

1. SqlSession 的创建方式:通过 SqlSessionFactory 工厂

SqlSession 的创建完全依赖于 SqlSessionFactory 工厂。 SqlSessionFactory 接口提供了多个 openSession() 方法的重载版本,用于创建不同类型的 SqlSession 实例。 最常用的创建 SqlSession 的方式是通过 SqlSessionFactory.openSession() 方法。

常见的 SqlSessionFactory.openSession() 方法调用方式:

  • SqlSession openSession() (最常用):

    SqlSessionFactory sqlSessionFactory = ...; // 假设已经创建了 SqlSessionFactory 实例
    SqlSession sqlSession = sqlSessionFactory.openSession(); // 创建一个新的 SqlSession 实例
    
    • 这是最常用的方式,创建一个默认配置的 SqlSession 实例
    • 默认情况下,SqlSession 实例不会自动提交事务 (autoCommit = false)。 需要手动调用 sqlSession.commit() 提交事务,或 sqlSession.rollback() 回滚事务。
    • 默认情况下,SqlSession 使用 ExecutorType.SIMPLE 执行器。
  • SqlSession openSession(boolean autoCommit):

    SqlSession sqlSession = sqlSessionFactory.openSession(true); // 创建一个自动提交事务的 SqlSession 实例
    
    • 创建一个 SqlSession 实例,并 设置事务是否自动提交
    • autoCommit = true: SqlSession 会自动提交事务。 每次执行 SQL 语句后,事务会自动提交。 适用于不需要手动控制事务的简单场景。
    • autoCommit = false: SqlSession 不会自动提交事务 (默认值)。 需要手动调用 sqlSession.commit()sqlSession.rollback() 来管理事务。 适用于需要手动控制事务边界的场景。
  • SqlSession openSession(ExecutorType executorType):

    SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH); // 创建一个使用 BATCH 执行器的 SqlSession 实例
    
    • 创建一个 SqlSession 实例,并 指定使用的执行器类型 (ExecutorType)
    • ExecutorType 是一个枚举,定义了 MyBatis 执行 SQL 语句的不同执行器类型:
      • ExecutorType.SIMPLE (默认): 简单执行器。 每次执行 SQL 语句都会创建一个新的 Statement 对象。 性能相对较低,但实现简单。
      • ExecutorType.REUSE: 复用执行器。 复用 Statement 对象。 如果执行相同的 SQL 语句 (只是参数不同),可以复用 Statement 对象,提高性能。
      • ExecutorType.BATCH: 批量执行器。 支持批量执行 SQL 语句,可以显著提高批量操作的性能。 适用于批量插入、批量更新等场景。
  • SqlSession openSession(TransactionIsolationLevel level) (已过时):

    // @Deprecated in MyBatis 3.5.x and removed in MyBatis 3.6.x
    // SqlSession sqlSession = sqlSessionFactory.openSession(TransactionIsolationLevel.READ_COMMITTED);
    
    • 已过时 (Deprecated) 且已移除: 在 MyBatis 3.5.x 中被标记为过时,并在 MyBatis 3.6.x 中被移除。 不再推荐使用此方法,事务隔离级别应该在数据源连接池或事务管理器中配置。
  • SqlSession openSession(ExecutorType executorType, boolean autoCommit):

    SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.REUSE, true); // 创建一个使用 REUSE 执行器并自动提交事务的 SqlSession 实例
    
    • 创建一个 SqlSession 实例,同时指定执行器类型和是否自动提交事务
    • 结合了 openSession(ExecutorType executorType)openSession(boolean autoCommit) 两个方法的参数。
  • SqlSession openSession(Connection connection):

    Connection connection = ...; // 假设已经获取了 JDBC Connection 对象 (例如从数据源)
    SqlSession sqlSession = sqlSessionFactory.openSession(connection); // 使用已有的 Connection 对象创建 SqlSession 实例
    
    • 创建一个 SqlSession 实例,并 使用已有的 JDBC Connection 对象
    • 适用于需要 复用外部事务管理 的场景,例如在 Spring 事务管理下,Spring 会提供 Connection 对象,MyBatis 可以复用 Spring 管理的 Connection 和事务。
    • 使用此方法创建的 SqlSession 不会从数据源获取新的连接,而是直接使用传入的 Connection 对象。 SqlSession 也不会负责关闭传入的 Connection 对象,连接的关闭责任由外部调用者承担。
  • SqlSession openSession(ExecutorType executorType, TransactionIsolationLevel level) (已过时):

    // @Deprecated in MyBatis 3.5.x and removed in MyBatis 3.6.x
    // SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH, TransactionIsolationLevel.SERIALIZABLE);
    
    • 已过时 (Deprecated) 且已移除: 同样被标记为过时并移除,不推荐使用。
  • SqlSession openSession(ExecutorType executorType, Connection connection):

    Connection connection = ...;
    SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH, connection); // 创建一个使用 BATCH 执行器并使用已有 Connection 的 SqlSession 实例
    
    • 创建一个 SqlSession 实例,同时指定执行器类型和使用已有的 JDBC Connection 对象
    • 结合了 openSession(ExecutorType executorType)openSession(Connection connection) 两个方法的参数。
  • SqlSession openSession(ExecutorType executorType, boolean autoCommit, TransactionIsolationLevel level) (已过时):

    // @Deprecated in MyBatis 3.5.x and removed in MyBatis 3.6.x
    // SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.REUSE, true, TransactionIsolationLevel.REPEATABLE_READ);
    
    • 已过时 (Deprecated) 且已移除: 同样被标记为过时并移除,不推荐使用。

2. SqlSessionSqlSessionFactory 的关系:工厂和产品

SqlSessionSqlSessionFactory 之间是典型的 工厂模式 (Factory Pattern) 的关系:

  • SqlSessionFactory 是工厂 (Factory):

    • SqlSessionFactory 接口及其实现类 (通常是 DefaultSqlSessionFactory) 充当 工厂 的角色。
    • SqlSessionFactory 的职责是创建和管理 SqlSession 实例。 它负责创建 SqlSession 对象,并为 SqlSession 提供必要的配置信息 (例如 Configuration 对象)。
    • SqlSessionFactory 是一个 重量级对象,创建过程相对耗时,但在应用的整个生命周期中,通常 只需要创建一个 SqlSessionFactory 实例 (单例)
  • SqlSession 是产品 (Product):

    • SqlSession 接口及其实现类 (通常是 DefaultSqlSession) 充当 产品 的角色。
    • SqlSession 是 MyBatis 与数据库交互的主要接口。 开发者通过 SqlSession 执行 SQL 语句、管理事务、获取 Mapper 接口代理对象等。
    • SqlSession 是一个 轻量级对象,创建速度快。 但 SqlSession 不是线程安全的。 最佳实践是 在每个线程中获取一个新的 SqlSession 实例,并在使用完成后及时关闭 (sqlSession.close())。 通常,SqlSession 的生命周期应该 尽可能短 (Request-Scoped)

关系总结:

  • SqlSessionFactorySqlSession 的工厂,负责创建 SqlSession 实例。
  • SqlSessionFactory 是单例的 (Singleton),在应用生命周期内通常只有一个实例。
  • SqlSession 是非线程安全的,轻量级的,通常是请求作用域 (Request-Scoped) 的,每次数据库操作都应该获取新的 SqlSession 实例。
  • SqlSessionFactory 内部持有 Configuration 对象,SqlSessionSqlSessionFactory 获取 Configuration 信息,并使用 Configuration 进行 SQL 执行、结果映射等操作.

简单比喻:

你可以将 SqlSessionFactory 比喻成一个 汽车工厂,而 SqlSession 比喻成 工厂生产的汽车

  • 汽车工厂 (SqlSessionFactory): 负责生产汽车 (SqlSession)。 工厂本身很大,建造工厂成本很高 (创建 SqlSessionFactory 耗时),但工厂可以持续生产汽车。
  • 汽车 (SqlSession): 工厂生产的产品,用于实际的驾驶 (数据库操作)。 汽车相对轻便,容易生产 (创建 SqlSession 速度快),但汽车是消耗品,需要定期维护和更换 ( SqlSession 不是线程安全的,需要短生命周期)。

3. SqlSession 的生命周期和使用:

  • 获取 SqlSession: 通过 SqlSessionFactory.openSession() 方法获取 SqlSession 实例。
  • 执行数据库操作: 使用 SqlSession 提供的各种方法 (例如 selectOne(), selectList(), insert(), update(), delete(), getMapper() 等) 执行 SQL 语句或获取 Mapper 接口代理对象。
  • 管理事务 (如果 autoCommit = false):
    • sqlSession.commit(): 提交事务。
    • sqlSession.rollback(): 回滚事务。
  • 关闭 SqlSession: 务必在使用完成后及时关闭 SqlSession (sqlSession.close()). close() 方法会释放 SqlSession 占用的资源 (例如 JDBC 连接),并将其归还给连接池 (如果使用了连接池数据源)。 不及时关闭 SqlSession 会导致资源泄漏,影响系统性能和稳定性。 通常在 finally 块中关闭 SqlSession,确保无论是否发生异常,SqlSession 都能被正确关闭。

代码示例 (完整的 SqlSession 使用流程):

SqlSession sqlSession = null;
try {sqlSession = sqlSessionFactory.openSession(); // 获取 SqlSession 实例UserMapper userMapper = sqlSession.getMapper(UserMapper.class); // 获取 Mapper 接口代理对象User user = userMapper.getUserById(1); // 执行 SQL 操作// ... 其他数据库操作 ...sqlSession.commit(); // 提交事务 (如果 autoCommit = false)return user;} catch (Exception e) {if (sqlSession != null) {sqlSession.rollback(); // 回滚事务 (如果发生异常)}throw e; // 抛出异常
} finally {if (sqlSession != null) {sqlSession.close(); // 关闭 SqlSession, 释放资源}
}

总结:

SqlSession 是 MyBatis 与数据库交互的核心接口,它通过 SqlSessionFactory 工厂创建。 SqlSessionFactory 是重量级对象,负责创建和配置 SqlSession,而 SqlSession 是轻量级对象,用于执行 SQL 语句和管理事务。 理解 SqlSession 的创建方式和与 SqlSessionFactory 的关系,以及 SqlSession 的生命周期管理,对于正确使用 MyBatis 至关重要。 在 MyBatis 应用中,开发时遵循 “获取 SqlSession -> 执行数据库操作 -> 管理事务 -> 关闭 SqlSession 的标准流程,确保资源正确释放和事务的正确性。


http://www.ppmy.cn/devtools/168109.html

相关文章

从零开始写C++3D游戏引擎(开发环境VS2022+OpenGL)之十一 从打光到材质 细嚼慢咽逐条读代码系列

写在篇前的话 作为一个曾经在代码堆里面苦苦挣扎的萌新,困惑的事情在于库,各种依赖,包换文件,链接库,纠结于代码的作用意义。尤其在3D引擎开发的问题上,很多人都被各种困难给阻拦,放弃了在3D渲染,3D游戏引擎上大涨鸿图的机会。 当然关于3D游戏引擎的教程已经汗牛充栋…

机器学习中说的正向传递和反向传递是什么意思

在机器学习,尤其是深度学习领域,​正向传递(Forward Pass)​和反向传递(Backward Pass)​是神经网络训练过程中的两个核心步骤。它们共同构成了训练神经网络的基础框架,通常与梯度下降算法结合使…

数学建模历程之初见

第一次接触数学建模是在上大学前,当时只是听过。起源于我在大学的老乡群里聊天,由于当时年轻有点傻,说的话太多了,什么都问哈哈哈哈哈。 后来有个学长从老乡群里加我,问我怎么话那么多,你们懂当时对我幼小…

大数据学习拓展——Minio安装与使用

本文参考:如何在ubuntu上搭建minio_ubuntu minio-CSDN博客文章浏览阅读2.9k次。本文主要介绍了在ubuntu服务器下部署minio的过程,以及如何通过客户端进行简单操作。_ubuntu miniohttps://blog.csdn.net/bDreamer/article/details/130161669 MinIO是一个…

单元测试、注解

目录 一、单元测试1.快速入门2.Junit在实际开发中的用法 二、注解1.注解概述2.自定义注解3.元注解4.解析注解 一、单元测试 单元测试就是针对最小的功能单元编写测试代码,Java程序最小的功能单元是方法。因此,单元测试就是针对Java方法的测试&#xff0…

【工具】huggingface 模型下载过程

前述 记录下自己下载模型的几种方式 方式 1、网页直接浏览器下载: 简单,但是随时可能断 2、git lfs # 拉代码 GIT_LFS_SKIP_SMUDGE1 git clone https://huggingface.co/stabilityai/stable-diffusion-xl-base-1.0 # 进入目录 cd stable-diffusion-…

学习笔记 ASP.NET Core Web API 8.0部署到iis

一.修改配置文件 修改Program.cs配置文件将 if (app.Environment.IsDevelopment()) {app.UseSwagger();app.UseSwaggerUI(); }修改为 app.UseSwagger(); app.UseSwaggerUI(); 二.安装ASP.NET Core Runtime 8.0.14 文件位置https://dotnet.microsoft.com/en-us/download/do…

【GPT入门】第23课 langchain serve介绍

【GPT入门】第23课 langchain serve介绍 1. langchain介绍2. 思路3.代码1. langchain介绍 langserve 是一个用于简化 LangChain 应用部署的工具,它可以将使用 LangChain 构建的链(chains)、代理(agents)等组件快速转化为 RESTful API 服务,下面从多个方面详细介绍它的作…