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

相关推荐
南城花随雪。5 小时前
Mybatis框架之模板方法模式 (Template Method Pattern)
java·mybatis·模板方法模式
水w9 小时前
单例模式的几种实现方式
java·开发语言·jvm·单例模式·单例
basic_code18 小时前
Spring boot 整合mybatis-plus
java·spring boot·mybatis·mybatis-plus
鸿·蒙1 天前
【MyBatis 源码阅读与笔记】Mapper 接口的动态代理实现
java·mybatis
redemption_21 天前
mybatis 动态SQL语句
java·jvm·mybatis
北执南念1 天前
Mybatis-Plus 多租户插件&属性自动赋值
java·mybatis
Atlasgorov1 天前
JAVA_单例模式
java·开发语言·单例模式
捕鲸叉1 天前
C++单例模式与多例模式
开发语言·c++·单例模式
程序员黄同学1 天前
请描述一下Spring Boot中的@SpringBootApplication注解的工作原理?
java·spring boot·mybatis