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

相关推荐
秋恬意9 小时前
Mybatis能执行一对一、一对多的关联查询吗?都有哪些实现方式,以及它们之间的区别
java·数据库·mybatis
越甲八千18 小时前
重温设计模式--单例模式
单例模式·设计模式
Vincent(朱志强)18 小时前
设计模式详解(十二):单例模式——Singleton
android·单例模式·设计模式
张铁铁是个小胖子19 小时前
MyBatis学习
java·学习·mybatis
hanbarger1 天前
mybatis框架——缓存,分页
java·spring·mybatis
乘风御浪云帆之上1 天前
数据库操作【JDBC & HIbernate & Mybatis】
数据库·mybatis·jdbc·hibernate
向阳12182 天前
mybatis 动态 SQL
数据库·sql·mybatis
新手小袁_J2 天前
JDK11下载安装和配置超详细过程
java·spring cloud·jdk·maven·mybatis·jdk11
xlsw_2 天前
java全栈day20--Web后端实战(Mybatis基础2)
java·开发语言·mybatis
cmdch20173 天前
Mybatis加密解密查询操作(sql前),where要传入加密后的字段时遇到的问题
数据库·sql·mybatis