第十二节 SpringBoot项目如何同时使用两个数据源

亮子 2025-11-05 10:08:55 32 0 0 0

1、添加必要依赖

demo我是使用的SpringBoot 3.5.7,但思路都是一样的

<dependency>
    <groupId>com.mysql</groupId>
    <artifactId>mysql-connector-j</artifactId>
    <scope>runtime</scope>
</dependency>

<!-- MyBatis-Plus依赖 -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-spring-boot3-starter</artifactId>
    <version>3.5.7</version>
</dependency>

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.38</version>
</dependency>

2、第一个数据源的配置

PrimaryDataSourceConfig.java文件

package com.bwie.serverdemojdk17.config;

import com.baomidou.mybatisplus.autoconfigure.ConfigurationCustomizer;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;

/**
 * @author 军哥
 * @version 1.0
 * @description: TODO
 * @date 2025/11/4 18:31
 */

@Configuration
// 扫描主数据源对应的Mapper接口(指定包路径,避免与第二个数据源冲突)
@MapperScan(
        basePackages = "com.bwie.serverdemojdk17.mapper.primary", // 主数据源的Mapper包
        sqlSessionFactoryRef = "primarySqlSessionFactory"
)
public class PrimaryDataSourceConfig {

    // 创建主数据源
    @Primary
    @Bean(name = "primaryDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.primary") // 对应配置文件中的前缀
    public DataSource primaryDataSource() {
        return DataSourceBuilder.create().build();
    }

    // 创建主数据源的事务管理器
    @Primary
    @Bean(name = "primaryTransactionManager")
    public DataSourceTransactionManager primaryTransactionManager(
            @Qualifier("primaryDataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    // 创建主数据源的SqlSessionFactory(MyBatis专用)
    @Primary
    @Bean(name = "primarySqlSessionFactory")
    public MybatisSqlSessionFactoryBean primarySqlSessionFactory(
            @Qualifier("primaryDataSource") DataSource dataSource) throws Exception {
        MybatisSqlSessionFactoryBean sessionFactory = new MybatisSqlSessionFactoryBean();
        sessionFactory.setDataSource(dataSource);
        // 若有MyBatis配置文件,可指定路径(如mapper.xml)
        // sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver()
        //     .getResources("classpath:mapper/primary/*.xml"));
        return sessionFactory;
    }
    
    /**
     * MyBatis-Plus配置
     */
    @Bean
    @Primary
    public ConfigurationCustomizer primaryConfigurationCustomizer() {
        return configuration -> {
            configuration.setMapUnderscoreToCamelCase(true);
        };
    }
}

3、第二个数据源的配置

package com.bwie.serverdemojdk17.config;


import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;

/**
 * @author 军哥
 * @version 1.0
 * @description: TODO
 * @date 2025/11/4 18:33
 */

@Configuration
// 扫描第二个数据源对应的Mapper接口
@MapperScan(
        basePackages = "com.bwie.serverdemojdk17.mapper.secondary", // 第二个数据源的Mapper包
        sqlSessionFactoryRef = "secondarySqlSessionFactory"
)
public class SecondaryDataSourceConfig {

    @Bean(name = "secondaryDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.secondary")
    public DataSource secondaryDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "secondaryTransactionManager")
    public DataSourceTransactionManager secondaryTransactionManager(
            @Qualifier("secondaryDataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean(name = "secondarySqlSessionFactory")
    public MybatisSqlSessionFactoryBean secondarySqlSessionFactory(
            @Qualifier("secondaryDataSource") DataSource dataSource) throws Exception {
        MybatisSqlSessionFactoryBean sessionFactory = new MybatisSqlSessionFactoryBean();
        sessionFactory.setDataSource(dataSource);
        // 若有MyBatis配置文件,指定路径
        // sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver()
        //     .getResources("classpath:mapper/secondary/*.xml"));
        return sessionFactory;
    }
}

4、配置文件

spring:
  application:
    name: server-demo-jdk17

  datasource:
    # 第一个数据源(主数据源)
    primary:
      jdbc-url: jdbc:mysql://localhost:3306/db_quanzi?autoReconnect=true&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
      username: root
      password: root
      driver-class-name: com.mysql.cj.jdbc.Driver
    # 第二个数据源
    secondary:
      jdbc-url: jdbc:mysql://localhost:3306/db_health?autoReconnect=true&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
      username: root
      password: root
      driver-class-name: com.mysql.cj.jdbc.Driver

# 若使用MyBatis,可配置 mapper 扫描路径(可选,也可在配置类中指定)
mybatis:
  mapper-locations: classpath:mapper/*.xml

# MyBatis-Plus配置(可选)
mybatis-plus:
  # Mapper.xml文件路径(若放在resources/mapper目录下)
  mapper-locations: classpath:mapper/*.xml
  # 实体类包路径(用于自动扫描实体类)
  type-aliases-package: com.bwie.serverdemojdk17.entity
  configuration:
    # 开启SQL日志打印(方便调试)
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    # 开启驼峰命名转换(如数据库字段user_name -> 实体类userName)
    map-underscore-to-camel-case: true

5、使用两个数据

package com.bwie.serverdemojdk17.service.impl;

import com.bwie.serverdemojdk17.entity.TbAsk;
import com.bwie.serverdemojdk17.entity.TbUser;
import com.bwie.serverdemojdk17.mapper.primary.TbUserMapper;
import com.bwie.serverdemojdk17.mapper.secondary.TbAskMapper;
import com.bwie.serverdemojdk17.service.TestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;

/**
 * @author 军哥
 * @version 1.0
 * @description: TODO
 * @date 2025/11/4 19:02
 */

@Service
public class TestServiceImpl implements TestService {

    // 注入主数据源的Mapper
    @Autowired
    private TbUserMapper primaryUserMapper;

    // 注入第二个数据源的Mapper
    @Autowired
    private TbAskMapper secondaryUserMapper;

    @Override
    public Object getList() {

        HashMap<String, Object> map = new HashMap<>();

        List<TbUser> tbUsers = primaryUserMapper.selectList(null);
        map.put("tbUsers", tbUsers);

        List<TbAsk> tbAsks = secondaryUserMapper.selectList(null);
        map.put("tbAsks", tbAsks);

        return map;
    }
}

源代码地址

https://gitee.com/ywbingchuan/server-demo-jdk17.git