Mybatis框架之单例模式 (Singleton Pattern)

embedded/2024/11/19 13:48:42/

MyBatis 框架中也使用到了单例模式 (Singleton Pattern),主要体现在 SqlSessionFactory 的创建和管理上。通过单例模式,MyBatis 可以确保整个应用程序中只创建一个 SqlSessionFactory 实例,从而有效地管理数据库连接资源并提高性能。下面将详细介绍 MyBatis 中的单例模式的应用原理和实现方式。

1. 什么是单例模式 (Singleton Pattern)?

单例模式 是一种创建型设计模式,确保一个类在整个应用程序中只有一个实例,并提供一个全局访问点来访问该实例。这种模式通常用于需要被频繁访问且只能存在一个实例的对象,例如数据库连接池、线程池、配置管理器等。

单例模式的特点:

  • 唯一性:整个应用程序中只存在一个实例。
  • 全局访问:提供一个全局访问点供其他代码使用。
  • 延迟加载 (Lazy Initialization)(可选):可以在第一次使用时创建实例,从而节省资源。

2. MyBatis 中的单例模式应用

在 MyBatis 中,SqlSessionFactory 就是一个典型的单例模式的实现。SqlSessionFactory 是创建 SqlSession 对象的工厂,它负责解析 MyBatis 配置文件,并管理数据库连接资源。

2.1 为什么 SqlSessionFactory 需要单例模式
  • 性能考虑:创建 SqlSessionFactory 是一个相对耗时的操作,需要解析配置文件、初始化连接池等。因此,确保 SqlSessionFactory 只被创建一次,可以减少重复的资源开销,提高性能。
  • 资源管理:使用单例模式可以确保整个应用程序中只有一个 SqlSessionFactory 实例,从而有效地管理数据库连接资源。
  • 线程安全SqlSessionFactory 本身是线程安全的,可以在多个线程中安全地共享。

3. SqlSessionFactory单例模式实现

通常,我们会通过封装一个工具类来实现 SqlSessionFactory单例模式。下面是一个基于单例模式SqlSessionFactory 实现示例:

3.1 MyBatis 配置文件 (mybatis-config.xml)
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><environments default="development"><environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="com.mysql.cj.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/mydatabase"/><property name="username" value="root"/><property name="password" value="password"/></dataSource></environment></environments><mappers><mapper resource="com/example/mapper/UserMapper.xml"/></mappers>
</configuration>
3.2 创建单例模式MyBatisUtil 工具类
import java.io.InputStream;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;public class MyBatisUtil {// 静态变量,用于存储唯一的 SqlSessionFactory 实例private static SqlSessionFactory sqlSessionFactory;// 私有构造函数,防止外部实例化private MyBatisUtil() {}// 获取 SqlSessionFactory 的方法public static SqlSessionFactory getSqlSessionFactory() {if (sqlSessionFactory == null) {synchronized (MyBatisUtil.class) {if (sqlSessionFactory == null) {try {String resource = "mybatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(resource);sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);} catch (Exception e) {e.printStackTrace();}}}}return sqlSessionFactory;}
}
3.3 使用 MyBatisUtil 获取 SqlSession
import org.apache.ibatis.session.SqlSession;
import com.example.mapper.UserMapper;
import com.example.model.User;
import java.util.List;public class MyBatisExample {public static void main(String[] args) {// 通过单例模式获取 SqlSessionFactorySqlSessionFactory sqlSessionFactory = MyBatisUtil.getSqlSessionFactory();try (SqlSession session = sqlSessionFactory.openSession()) {// 获取 Mapper 接口的实现UserMapper userMapper = session.getMapper(UserMapper.class);// 调用方法执行 SQLList<User> users = userMapper.getAllUsers();users.forEach(user -> System.out.println(user.getName()));}}
}

4. 解析单例模式实现细节

  1. 私有化构造方法

    • 通过将构造函数设为 private,防止外部创建实例,从而确保类的唯一实例性。
  2. 双重检查锁 (Double-Checked Locking)

    • 使用 synchronized 关键字和双重检查锁机制确保 SqlSessionFactory 的线程安全。这可以避免在多线程环境下重复创建实例的问题。
  3. 延迟加载 (Lazy Initialization)

    • 只有在第一次调用 getSqlSessionFactory() 方法时,才会创建 SqlSessionFactory 实例,这样可以节省系统资源。

5. 单例模式的优缺点

优点:
  • 节省资源:避免重复创建 SqlSessionFactory 实例,节省内存和 CPU 资源。
  • 全局访问:提供了一个全局访问点,方便使用。
  • 线程安全:通过双重检查锁机制,可以确保在多线程环境下的安全性。
缺点:
  • 生命周期管理:由于单例对象在整个应用程序生命周期中都存在,可能会导致资源不能及时释放,从而增加内存消耗。
  • 不易测试单例模式会增加代码的耦合度,可能会给单元测试带来一定困难。

6. 总结

MyBatis 通过单例模式管理 SqlSessionFactory 的创建和访问,从而提高了系统性能并简化了数据库连接的管理。在实际项目中,SqlSessionFactory 通常是单例的,因为它是线程安全的,且创建过程相对耗时。

使用单例模式可以确保 SqlSessionFactory 只被创建一次,从而避免重复创建造成的资源浪费。这种设计模式在 MyBatis 的实际应用中非常常见,是数据库访问层优化的一个重要手段。


http://www.ppmy.cn/embedded/138776.html

相关文章

wsl配置ubuntu22.04,并配置docker

wsl配置ubuntu22.04&#xff0c;并配置docker 文章目录 wsl配置ubuntu22.04&#xff0c;并配置docker一、在Windows上安装Linux子系统前提条件安装步骤 二、wsl安装系统到其他盘①查看wsl运行状态&#xff0c;将其保持在关闭状态②导出当前Linux的镜像③注销之前的系统并检查④…

系统思考—跳出症状看全局

在和企业创办人交流中&#xff0c;经常听到这样的疑问&#xff1a;“为什么我们试了这么多办法&#xff0c;问题却还是没有解决&#xff1f;”其实很多时候&#xff0c;根本原因并不在于对策不到位&#xff0c;而是连问题的本质都没找对。 曾经和一家企业合作&#xff0c;为了解…

大数据-225 离线数仓 - 目前需求分析 指标口径 日志数据采集 taildir source HDFS Sink Agent Flume 优化配置

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff08;已更完&#xff09;HDFS&#xff08;已更完&#xff09;MapReduce&#xff08;已更完&am…

栈Stack和队列Queue

目录 一、栈 &#xff08;1&#xff09;用数组实现 &#xff08;2&#xff09;用单链表实现 &#xff08;3&#xff09;用标注尾结点的单链表实现 &#xff08;4&#xff09;用双向链表实现 2、栈的实际应用 &#xff08;1&#xff09;改变元素的序列 &#xff08;2&am…

学习日记_20241110_聚类方法(K-Means)

前言 提醒&#xff1a; 文章内容为方便作者自己后日复习与查阅而进行的书写与发布&#xff0c;其中引用内容都会使用链接表明出处&#xff08;如有侵权问题&#xff0c;请及时联系&#xff09;。 其中内容多为一次书写&#xff0c;缺少检查与订正&#xff0c;如有问题或其他拓展…

R语言/Rstudio 报错

记录R语言和Rstudio的报错&#xff1a; 1. Error 28 (inotify_add_watch: No watches available) File monitoring failed for project at "~xxx" Error 28 (inotify_add_watch: No watches available) Features disabled: R source file indexing, Diagnostics不少…

力扣(leetcode)题目总结——辅助栈篇

leetcode 经典题分类 链表数组字符串哈希表二分法双指针滑动窗口递归/回溯动态规划二叉树辅助栈 本系列专栏&#xff1a;点击进入 leetcode题目分类 关注走一波 前言&#xff1a;本系列文章初衷是为了按类别整理出力扣&#xff08;leetcode&#xff09;最经典题目&#xff0c…

【C++之STL】摸清 string 的模拟实现(上)

文章目录 1. 为什么要模拟实现&#xff1f;2. 基本框架搭建3. 构造函数3. 1 默认构造/from c_str3. 2 拷贝构造3. 2. 1 深浅拷贝 3. 3 fill3. 4 迭代器区间构造 4. 容量操作4. 1 size()和capacity()和empty()4. 2 clear()4. 3 resize()4. 4 reserve() 1. 为什么要模拟实现&…