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

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 复制代码
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
    PUBLIC "-//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 工具类
java 复制代码
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
java 复制代码
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) {
        // 通过单例模式获取 SqlSessionFactory
        SqlSessionFactory sqlSessionFactory = MyBatisUtil.getSqlSessionFactory();

        try (SqlSession session = sqlSessionFactory.openSession()) {
            // 获取 Mapper 接口的实现
            UserMapper userMapper = session.getMapper(UserMapper.class);

            // 调用方法执行 SQL
            List<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 的实际应用中非常常见,是数据库访问层优化的一个重要手段。

相关推荐
计算机学姐43 分钟前
基于SpringBoot的公务员考试管理系统【题库组卷+考试练习】
java·vue.js·spring boot·后端·java-ee·intellij-idea·mybatis
阿巴~阿巴~9 小时前
线程安全单例模式与懒汉线程池的实现与优化
linux·服务器·单例模式·线程池·饿汉模式·懒汉模式·静态方法
不光头强9 小时前
Java中的单例模式
单例模式
崎岖Qiu9 小时前
【设计模式笔记17】:单例模式1-模式分析
java·笔记·单例模式·设计模式
虾说羊11 小时前
创建对象中的单例模式
单例模式
她说彩礼65万15 小时前
C#设计模式 单例模式实现方式
单例模式·设计模式·c#
刘一说21 小时前
深入解析 Spring Boot 数据访问:Spring Data JPA 与 MyBatis 集成实战
spring boot·tomcat·mybatis
赋能大师兄1 天前
MyBatis缓存机制
mybatis·二级缓存·一级缓存
nice_lcj5201 天前
认识多线程:单例模式
java·开发语言·单例模式
Adellle1 天前
2.单例模式
java·开发语言·单例模式