MyBatis SqlSessionFactory 是如何创建的?

SqlSessionFactory 是 MyBatis 的核心接口之一,它是创建 SqlSession 实例的工厂。 SqlSession 实例是 MyBatis 与数据库交互的主要接口,负责执行 SQL 语句、管理事务等。

SqlSessionFactory 的创建过程主要由 SqlSessionFactoryBuilder 类负责。 SqlSessionFactoryBuilder 遵循建造者模式,提供多种构建 SqlSessionFactory 的方法,可以从不同的配置源 (如 XML 配置文件、Java 代码配置) 构建 SqlSessionFactory 实例。

以下是 SqlSessionFactory 的详细创建步骤,以及涉及的关键类和方法:

1. 获取 MyBatis 配置信息 (Configuration Source):

在创建 SqlSessionFactory 之前,首先需要加载和解析 MyBatis 的配置信息。 MyBatis 配置信息可以来源于以下几种方式:

  • XML 配置文件 (mybatis-config.xml 或自定义 XML 文件): 这是最常见的配置方式,通过 XML 文件定义 MyBatis 的全局配置、数据源、事务管理器、Mapper 映射文件等。
  • Java 代码配置 (使用 Configuration 类): 也可以使用 Java 代码直接构建 Configuration 对象,并设置各种配置项。
  • Spring 集成 (Spring Boot 或 Spring Framework): 当 MyBatis 与 Spring 集成时,Spring 容器会负责管理 SqlSessionFactory 的创建和生命周期,配置信息通常由 Spring 管理。

2. 使用 SqlSessionFactoryBuilder 构建 SqlSessionFactory:

SqlSessionFactoryBuilder 类提供了多个重载的 build() 方法,用于根据不同的配置源构建 SqlSessionFactory 实例。 最常用的 build() 方法接受一个 InputStream 参数,用于读取 XML 配置文件。

常见的 SqlSessionFactoryBuilder.build() 方法调用方式:

  • 从 XML 配置文件构建 (最常用):

    String resource = "mybatis-config.xml"; // MyBatis 配置文件路径
    InputStream inputStream = Resources.getResourceAsStream(resource); // 使用 Resources 工具类加载资源
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    
    • Resources.getResourceAsStream(resource): MyBatis 提供的 Resources 工具类,用于从类路径 (classpath) 或文件系统加载资源文件 (例如 XML 配置文件)。
    • new SqlSessionFactoryBuilder().build(inputStream): 创建 SqlSessionFactoryBuilder 实例,并调用 build(inputStream) 方法,传入配置文件的 InputStreambuild() 方法会解析 XML 配置文件,并构建 SqlSessionFactory 实例。
  • Configuration 对象构建 (Java 代码配置):

    Configuration configuration = new Configuration();
    // ... 通过 configuration 对象设置各种 MyBatis 配置,例如:
    // configuration.setEnvironment(environment);
    // configuration.addMapper(UserMapper.class);
    // ...SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration);
    
    • new Configuration(): 创建 Configuration 对象。
    • 通过 configuration 对象,可以使用其提供的 API 方法 (例如 setEnvironment(), addMapper(), getTypeHandlerRegistry(), getInterceptors(), getSettings(), getProperties() 等) 来设置 MyBatis 的各种配置项。
    • new SqlSessionFactoryBuilder().build(configuration): 调用 SqlSessionFactoryBuilderbuild(configuration) 方法,传入配置好的 Configuration 对象,构建 SqlSessionFactory 实例。

3. SqlSessionFactoryBuilder.build() 方法内部的详细步骤 (以 XML 配置为例):

SqlSessionFactoryBuilder.build(InputStream inputStream) 方法内部会执行以下关键步骤来创建 SqlSessionFactory

  • 3.1. 创建 XMLConfigBuilder 对象:

    XMLConfigBuilder parser = new XMLConfigBuilder(inputStream);
    
    • XMLConfigBuilder 是 MyBatis 提供的 XML 配置解析器,专门用于解析 MyBatis 的 XML 配置文件。
    • 构造 XMLConfigBuilder 时,需要传入配置文件的 InputStream
  • 3.2. 解析 XML 配置文件并构建 Configuration 对象:

    Configuration configuration = parser.parse();
    
    • 调用 XMLConfigBuilderparse() 方法,开始解析 XML 配置文件。
    • parse() 方法会读取 XML 配置文件中的各个元素 (例如 <configuration>, <environments>, <mappers>, <typeHandlers>, <plugins>, <settings>, <properties> 等),并根据 XML 文件的内容,构建并填充一个 Configuration 对象
    • XMLConfigBuilder.parse() 方法内部会完成以下主要工作:
      • 解析 <configuration> 根元素: 读取 <configuration> 元素下的子元素。
      • 解析 <properties> 元素: 加载外部属性文件或 <properties> 元素内部的属性配置。
      • 解析 <settings> 元素: 设置 MyBatis 的全局设置,例如缓存策略、延迟加载、日志配置等。
      • 解析 <typeAliases> 元素: 定义类型别名,简化类型名称的使用。
      • 解析 <typeHandlers> 元素: 注册自定义的类型处理器。
      • 解析 <objectFactory> 元素: 配置自定义的对象工厂。
      • 解析 <objectWrapperFactory> 元素: 配置自定义的对象包装工厂。
      • 解析 <reflectorFactory> 元素: 配置自定义的反射工厂。
      • 解析 <plugins> 元素: 注册插件 (拦截器)。
      • 解析 <environments> 元素: 配置 MyBatis 的运行环境 (例如 development, production)。
        • 解析 <environment> 元素: 配置具体的运行环境,包括 transactionManager (事务管理器) 和 dataSource (数据源)。
          • 解析 <transactionManager> 元素: 配置事务管理器 (例如 JDBC, MANAGED)。
          • 解析 <dataSource> 元素: 配置数据源 (例如 UNPOOLED, POOLED, JNDI),并设置数据源连接属性 (例如 driver, url, username, password)。
      • 解析 <mappers> 元素: 注册 Mapper 映射器。
        • 根据 <mapper> 元素的配置方式 (resource, url, class, package),加载 Mapper 映射文件或 Mapper 接口,并将 Mapper 信息添加到 Configuration 对象中。
          • 对于 XML Mapper 文件 (resource, url): 使用 XMLMapperBuilder 解析 Mapper XML 文件,并将 Mapper 语句 (SQL 映射) 解析到 Configuration 对象中。
          • 对于 Mapper 接口 (class, package): 将 Mapper 接口注册到 Configuration 对象中,后续在执行 SQL 时,MyBatis 会动态地为 Mapper 接口生成代理对象。
  • 3.3. 构建 SqlSessionFactory 实例:

    return build(configuration);
    
    • XMLConfigBuilder.parse() 方法最终会返回构建好的 Configuration 对象。
    • SqlSessionFactoryBuilder.build(InputStream inputStream) 方法内部会再次调用 build(configuration) 方法,将解析得到的 Configuration 对象传递给它。
    • SqlSessionFactoryBuilder.build(Configuration config) 方法会真正创建 DefaultSqlSessionFactory 实例,并将 Configuration 对象作为构造参数传入。
  • 3.4. 返回 SqlSessionFactory 实例:

    private SqlSessionFactory build(Configuration config) {return new DefaultSqlSessionFactory(config);
    }
    
    • SqlSessionFactoryBuilder.build(Configuration config) 方法会创建 DefaultSqlSessionFactory 实例,并将之前解析和构建的 Configuration 对象传递给 DefaultSqlSessionFactory 的构造器。
    • DefaultSqlSessionFactorySqlSessionFactory 接口的默认实现类,它内部持有 Configuration 对象,并负责创建 SqlSession 实例。
    • SqlSessionFactoryBuilder.build() 方法最终会返回创建好的 SqlSessionFactory 实例。

4. SqlSessionFactory 的生命周期:

  • SqlSessionFactory 一旦被创建,应该在应用的整个生命周期内都存在。 最佳实践是在应用启动时创建 SqlSessionFactory,并将其作为单例 (Singleton) 对象进行管理和使用。
  • 在 Spring 环境中,SqlSessionFactory 通常由 Spring 容器管理,声明为 Spring Bean,并由 Spring 负责其生命周期管理。

总结 SqlSessionFactory 创建的关键步骤:

  1. 加载 MyBatis 配置信息 (XML 配置文件或 Java 代码配置)。
  2. 创建 SqlSessionFactoryBuilder 实例。
  3. 调用 SqlSessionFactoryBuilder.build() 方法,传入配置信息 (例如 InputStreamConfiguration 对象)。
  4. SqlSessionFactoryBuilder.build() 内部:
    • 创建 XMLConfigBuilder (如果使用 XML 配置)。
    • XMLConfigBuilder 解析 XML 配置文件,构建并填充 Configuration 对象。
    • SqlSessionFactoryBuilder 使用 Configuration 对象创建 DefaultSqlSessionFactory 实例。
  5. 返回 SqlSessionFactory 实例。

SqlSessionFactory 的重要性:

  • SqlSession 工厂: SqlSessionFactorySqlSession 的工厂,负责创建 SqlSession 实例。
  • 配置中心: SqlSessionFactory 内部持有 Configuration 对象,包含了 MyBatis 的所有配置信息 (数据源、事务管理器、Mapper 映射、全局设置等)。 Configuration 对象是 MyBatis 配置信息的中心仓库。
  • 性能优化: SqlSessionFactory 是重量级对象,创建过程相对耗时,但创建后可以重复使用,避免了每次数据库操作都重新解析配置和创建工厂的开销。 将其作为单例管理可以提高性能。
  • 线程安全: SqlSessionFactory 本身是线程安全的,可以被多个线程共享使用。 但 SqlSession 实例不是线程安全的,每个线程应该拥有自己的 SqlSession 实例。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/73506.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

玩转python:通俗易懂掌握高级数据结构-collections模块之Counter

引言 Counter是Python中collections模块提供的一个强大工具&#xff0c;用于统计可哈希对象的出现次数。它非常适合用于频率统计、词频分析、数据聚合等场景。本文将详细介绍Counter的关键用法和特性&#xff0c;并通过8个丰富的案例帮助读者掌握其应用。 关键用法和特性表格 …

DeepSeek面试——分词算法

DeepSeek-V3 分词算法 一、核心算法&#xff1a;字节级BPE&#xff08;Byte-level BPE&#xff0c;BBPE&#xff09; DeepSeek-V3 采用 字节级BPE&#xff08;BBPE&#xff09; 作为核心分词算法&#xff0c;这是对传统 BPE&#xff08;Byte Pair Encoding&#xff09;算法的…

机器学习——正则化、欠拟合、过拟合、学习曲线

过拟合&#xff08;overfitting&#xff09;:模型只能拟合训练数据的状态。即过度训练。 避免过拟合的几种方法&#xff1a; ①增加全部训练数据的数量&#xff08;最为有效的方式&#xff09; ②使用简单的模型&#xff08;简单的模型学不够&#xff0c;复杂的模型学的太多&am…

Python:函数(一)

python函数相关的知识点 1. 函数定义与调用 定义&#xff1a;使用 def 关键字&#xff0c;后接函数名和参数列表。 def greet(name):"""打印问候语&#xff08;文档字符串&#xff09;"""print(f"Hello, {name}!") 调用&#xff1a…

关于Flutter中两种Widget的生命周期详解

目录 一、StatelessWidget 生命周期 二、StatefulWidget 生命周期 1. 创建阶段 2. State初始化阶段 3. 构建阶段 4. 更新阶段 5. 销毁阶段 三、核心对比与常见陷阱 四、面试回答技巧 以下是Flutter中两种核心Widget(StatelessWidget和StatefulWidget)生命周…

Linux 》》Ubuntu 18 LTS 之后的版本 修改IP地址 主机名

进入目录 /etc/netplan 修改 50-cloud-init.yaml 》保存文件后&#xff0c;执行以下命令应用更改&#xff1a; sudo netplan apply 》》 DHCP模式 修改主机名 hostnamectl set-hostname xxxx 修改cloud.cfg 防止重启主机名还原 但测试下来 不修改&#xff0c; 重启 也不会还…

C++基础 [三] - 面向对象三

初始化列表 首先&#xff0c;初始化列表是我们的祖师爷本贾尼博士为了解决在某些成员变量在定义时必须初始化的情况。这个初始化列表其实发生在构造函数之前&#xff0c;也就是实例化整个对象时先对所有的成员都进行了初始化 初始化的概念区分 在之前的博客学习中&#xff…

55年免费用!RevoUninstaller Pro专业版限时领取

今天&#xff0c;我要给大家介绍一款超给力的卸载工具——RevoUninstaller Pro。这是一款由保加利亚团队精心打造的专业级卸载软件&#xff0c;堪称软件卸载界的“神器”。 RevoUninstaller分为免费版和专业版。专业版功能更为强大&#xff0c;但通常需要付费才能解锁全部功能。…

目前人工智能的发展,判断10年、20年后的人工智能发展的主要方向,或者带动的主要产业

根据2025年的最新行业研究和技术演进趋势&#xff0c;结合历史发展轨迹&#xff0c;未来10-20年人工智能发展的主要方向及带动的产业将呈现以下六大核心趋势&#xff1a; 一、算力革命与底层架构优化 核心地位&#xff1a;算力将成为类似“新能源电池”的基础设施&#xff0c;…

【机器人】复现 ASGrasp 通用透明物体重建、6-DoF抓取预测

在机器人抓取领域&#xff0c;透明和镜面物体的抓取一直是个难题。 ASGrasp核心是两层学习型立体网络&#xff0c;能够同时恢复透明和镜面物体的可见部分和不可见部分的深度信息。 然后融合两层深度信息&#xff0c;进行重建物体&#xff0c;得到点云信息作为GSNet&#xff0…

2. qt写带有槽的登录界面(c++)

我们在1.Qt写简单的登录界面(c)_c qt 设计一个简单界面-CSDN博客中写了个简单的登录界面&#xff0c;但没有槽&#xff0c;在这里写一个带有槽的界面。 1.代码 代码目录如下&#xff1a; main.cpp的代码如下&#xff1a; #include "MainWindow.h" #include <Qt…

windows安装两个或多个JDK,并实现自由切换

我用两个JDK来做演示&#xff0c;分别是JDK8和JDK17(本人已安装JDK8&#xff0c;所以这里只演示JDK17的安装)。 1、下载JDK17安装 Java Downloads | Oracle 2、安装JDK17,这里忽略。直接双击软件&#xff0c;点击下一步就可以。 3、配置环境变量 在系统变量中新建一个CLASSP…

【2025最新】深度学习框架PyTorch——从入门到精通(1)下载与安装

又名&#xff1a;芜湖起飞侠的PyTorch学习记录——从起飞到坠毁 简介安装内容总览安装AnacondaAnaconda简介Anaconda下载配置环境变量验证其他配置安装matplotlib 安装 CUDA安装之前安装cuDNN 安装torchCPU 版本安装GPU 版本安装通过pip安装&#xff08;不推荐&#xff09;通过…

C++数据结构1——栈结构详解

一、栈的基本概念与特性 1. 栈的定义与特点 栈&#xff08;Stack&#xff09;是一种遵循后进先出&#xff08;LIFO, Last In First Out&#xff09;原则的线性数据结构&#xff0c;其核心特征包括&#xff1a; 单端操作&#xff1a;所有操作仅通过栈顶进行 动态存储&#xf…

【Python 数据结构 15.哈希表】

目录 一、哈希表的基本概念 1.哈希表的概念 2.键值对的概念 3.哈希函数的概念 4.哈希冲突的概念 5.常用的哈希函数 Ⅰ、直接定址法 Ⅱ、平方取中法 Ⅲ、折叠法 Ⅳ、除留余数法 Ⅴ、位与法 6.哈希冲突的解决方案 Ⅰ、开放定址法 Ⅱ、链地址法 7.哈希表的初始化 8.哈希表的元素插…

历年云南大学计算机复试上机真题

历年云南大学计算机复试机试真题 在线评测&#xff1a;传送门&#xff1a;pgcode.cn 喝饮料 题目描述 商店里有 n 中饮料&#xff0c;第 i 种饮料有 mi 毫升&#xff0c;价格为 wi。 小明现在手里有 x 元&#xff0c;他想吃尽量多的饮料&#xff0c;于是向你寻求帮助&#x…

[文献阅读] 可变形卷积DCN - Deformable Convolutional Networks

**文献信息&#xff1a;**Deformable Convolutional Networks arxiv.org/abs/1703.06211 发表于ICCV 2017&#xff0c;提出了可变形卷积DCN&#xff08;Deformable ConvNets&#xff09; 摘要 卷积神经网络&#xff08;CNN&#xff09;由于其构建模块固定的几何结构天然地局限…

德语A1学习

Hast du morgen Zeit? Wann spielen wir? Vocabulary etwas/jemanden brauchen braucht, brauchte, hat gebraucht to need something/somebody Das geht. That works./Thats OK. den ganzen Tag the entire day dieser, diese, dieses this erst just; only G…

路局的上道检修过程中,利用AI视觉技术对轨道两旁设备设施进行检修

在铁路局的上道检修过程中,利用AI视觉技术对轨道两旁设备设施(如信号设备、电缆、接触网、通信设备等)以及铁路上方的电线(如接触网、电力线)进行异常检测,可以显著提高检修效率、降低人工成本并增强安全性。以下是具体的应用方案和技术路径: 1. 应用场景 1.1 轨道两旁…

函数指针/逗号表达式/不用if语句完成的字母输出题

1.函数指针用的不是那么频繁的一个操作&#xff1a; 下面是代码演示&#xff1a; 在这个int (*jump)(int);中 jump是这个指针变量名称&#xff0c;第一个int是指针类型&#xff0c;第二个int是指的这个指针所指的函数参数是int类型的。 #include <stdio.h>// 定义一个…