整合数据源

Druid

引言

本项目中我们采用了 MyBatis 作为 ORM 框架,并集成了阿里巴巴提供的 Druid 数据源管理工具来优化数据库连接的管理和性能。Druid 提供了强大的监控、扩展和配置能力,适用于大多数企业级应用场景。

添加 Druid 依赖

在项目的 pom.xml 文件中添加 Druid 的依赖配置,确保能够使用 Druid 进行数据源管理。

<dependency>
  <groupId>com.alibaba</groupId>
  <artifactId>druid</artifactId>
  <version>1.2.10</version>
</dependency>

配置 Druid 数据源与 MyBatis

在 MyBatis 配置类 MybatisConfig 中,通过以下步骤来整合 Druid 数据源:

  1. 创建并配置 Druid 数据源
  2. 使用 MyBatis 构建 SqlSessionFactorySqlSessionManager
  3. 将 Mapper 注册到 AOP 容器中

完整代码

package demo.mybatis.config;

import java.io.InputStream;
import java.util.Map;

import org.apache.ibatis.builder.xml.XMLMapperBuilder;
import org.apache.ibatis.logging.stdout.StdOutImpl;
import org.apache.ibatis.mapping.Environment;
import org.apache.ibatis.parsing.XNode;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.apache.ibatis.session.SqlSessionManager;
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;

import com.alibaba.druid.pool.DruidDataSource;
import com.litongjava.annotation.AConfiguration;
import com.litongjava.annotation.AInitialization;
import com.litongjava.jfinal.aop.AopManager;
import com.litongjava.tio.boot.server.TioBootServer;
import com.litongjava.tio.utils.hutool.ResourceUtil;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@AConfiguration
public class MybatisConfig {

  @Initialization
  public void sqlSessionFactory() {
    // 配置 Druid 数据源
    DruidDataSource dataSource = new DruidDataSource();
    dataSource.setDriverClassName("org.postgresql.Driver");
    dataSource.setUrl("jdbc:postgresql://192.168.3.9/defaultdb");
    dataSource.setUsername("postgres");
    dataSource.setPassword("123456");

    // 可选的 Druid 配置
    dataSource.setInitialSize(5);  // 初始连接数
    dataSource.setMaxActive(20);   // 最大活跃连接数
    dataSource.setMinIdle(5);      // 最小空闲连接数
    dataSource.setMaxWait(60000);  // 最大等待时间
    dataSource.setTestWhileIdle(true);  // 是否在空闲时进行连接检测
    dataSource.setTestOnBorrow(false);  // 借出连接时不检测
    dataSource.setTestOnReturn(false);  // 归还连接时不检测
    dataSource.setPoolPreparedStatements(true); // 是否开启 PSCache
    dataSource.setMaxPoolPreparedStatementPerConnectionSize(20); // 单个连接缓存的最大语句数

    try {
      dataSource.init(); // 初始化 Druid 数据源
    } catch (Exception e) {
      log.error("Druid 数据源初始化失败", e);
      return;
    }

    // 创建 MyBatis 配置对象
    Configuration configuration = new Configuration();
    configuration.setLogImpl(StdOutImpl.class); // 设置日志输出到控制台

    // 注册类型别名
    configuration.getTypeAliasRegistry().registerAliases("demo.mybatis.model");

    // 配置环境,包括事务管理器和数据源
    Environment environment = new Environment("development", new JdbcTransactionFactory(), dataSource);
    configuration.setEnvironment(environment);

    // 添加 Mapper
    addMapper(configuration, "SystemAdminMapper.xml");

    try {
      // 构建 SqlSessionFactory
      SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration);
      // 构建 SqlSessionManager
      SqlSessionManager sqlSessionManager = SqlSessionManager.newInstance(sqlSessionFactory);
      MySqlSessionManager.setSqlSessionManager(sqlSessionManager);

      // 将 Mapper 添加到 AOP 容器中
      addMapperToAop(sqlSessionManager);

      // 在应用关闭时,关闭 SqlSessionManager 和 Druid 数据源
      TioBootServer.me().addDestroyMethod(() -> {
        sqlSessionManager.close();
        dataSource.close(); // 关闭 Druid 数据源
      });
    } catch (Exception e) {
      log.error("无法创建 SqlSessionManager", e);
      throw new RuntimeException(e);
    }
  }

  private void addMapper(Configuration configuration, String resource) {
    // 加载并解析 Mapper XML 文件
    InputStream inputStream = ResourceUtil.getResourceAsStream(resource);
    if (inputStream == null) {
      throw new RuntimeException("无法找到资源文件:" + resource);
    }
    Map<String, XNode> sqlFragments = configuration.getSqlFragments();
    XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(inputStream, configuration, resource, sqlFragments);
    xmlMapperBuilder.parse();
  }

  private void addMapperToAop(SqlSessionManager sqlSessionManager) {
    // 获取所有注册的 Mapper 接口
    Configuration configuration = sqlSessionManager.getConfiguration();
    for (Class<?> mapperClass : configuration.getMapperRegistry().getMappers()) {
      // 获取 Mapper 实例
      Object mapperInstance = sqlSessionManager.getMapper(mapperClass);
      // 将 Mapper 实例添加到 AOP 容器中
      AopManager.me().addSingletonObject(mapperClass, mapperInstance);
      log.info("Mapper [{}] added to AOP", mapperClass.getName());
    }
  }
}

关键配置说明

Druid 数据源配置

  • setInitialSize(5): 初始创建的连接数为 5。
  • setMaxActive(20): 最大活跃连接数为 20,控制并发访问。
  • setMinIdle(5): 保持最小空闲连接数为 5,保证资源不浪费。
  • setMaxWait(60000): 最大等待时间为 60 秒,如果无法获取连接,将抛出异常。
  • setTestWhileIdle(true): 开启空闲连接的检查,避免因连接断开导致的异常。

Mapper 配置

  • 通过 addMapper 方法,使用 XMLMapperBuilder 加载并解析 MyBatis 的 Mapper XML 文件,确保 SQL 映射关系正常加载。

AOP 容器配置

  • 通过 addMapperToAop 方法,将 MyBatis 注册的所有 Mapper 接口实例通过 AopManager 添加到 AOP 容器中,方便在应用中使用。

总结

通过上述配置,您可以成功将 Druid 数据源集成到 MyBatis 项目中,从而优化数据库连接池的管理。