Springboot 实现多数据源(PostgreSQL 和 SQL Server)连接

Springboot 实现多数据源(PostgreSQL 和 SQL Server)连接

💡 作者:古渡蓝按

个人微信公众号 :微信公众号(深入浅出谈java)

感觉本篇对你有帮助可以关注一下,会不定期更新知识和面试资料、技巧!!!

在 Spring Boot 中同时连接 PostgreSQL 和 SQL Server 两个数据库,并结合 MyBatis-Plus 进行 ORM 操作,通常需要配置多数据源。以下提供一个完整的配置方案,包括依赖、配置文件、数据源配置类、MyBatis-Plus 集成以及使用示例

本次就以 PostgreSQLSQL Server 两个数据库示例

实现步骤

一、添加依赖

这里就添加对应数据库的依赖

xml 复制代码
<dependencies>
    <!-- Spring Boot Starter Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!-- MyBatis-Plus Starter -->
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.5.7</version>
    </dependency>

    <!-- PostgreSQL 驱动 -->
    <dependency>
        <groupId>org.postgresql</groupId>
        <artifactId>postgresql</artifactId>
        <scope>runtime</scope>
    </dependency>

    <!-- SQL Server 驱动 (推荐使用微软官方驱动) -->
    <dependency>
        <groupId>com.microsoft.sqlserver</groupId>
        <artifactId>mssql-jdbc</artifactId>
        <scope>runtime</scope>
    </dependency>

    <!-- 可选:连接池(Spring Boot 默认使用 HikariCP,无需额外添加) -->
</dependencies>

二、配置文件(application.yml)

配置两个数据源,使用自定义前缀区分:

注意配置好自己的地址和密码

yaml 复制代码
spring:
  datasource:
    # 主数据源(PostgreSQL)
    pg:
      jdbc-url: jdbc:postgresql://localhost:5432/your_pg_db
      username: pg_user
      password: pg_pass
      driver-class-name: org.postgresql.Driver
    # 次数据源(SQL Server)
    sqlserver:
      jdbc-url: jdbc:sqlserver://localhost:1433;databaseName=your_sql_db
      username: sa
      password: sql_pass
      driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver

三、多数据源配置类(核心)

分别创建两个数据源的配置类,并指定对应的 Mapper 扫描包、实体类包(可选)、SqlSessionFactory、TransactionManager 等。

Mapper 扫描包路径一定要在数据源配置的指定包下:

@MapperScan(basePackages = "com.example.mapper.pg", // 指定主数据源的 Mapper 包
sqlSessionFactoryRef = "pgSqlSessionFactory")

@MapperScan(basePackages = "com.example.mapper.sqlserver", // 指定次数据源的 Mapper 包
sqlSessionFactoryRef = "sqlserverSqlSessionFactory")

1. 主数据源配置(PostgreSQL)

java 复制代码
package com.example.config;

import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionTemplate;
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;

@Configuration
@MapperScan(basePackages = "com.example.mapper.pg",   // 指定主数据源的 Mapper 包
            sqlSessionFactoryRef = "pgSqlSessionFactory")
public class PgDataSourceConfig {

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

    @Primary
    @Bean(name = "pgSqlSessionFactory")
    public SqlSessionFactory pgSqlSessionFactory(@Qualifier("pgDataSource") DataSource dataSource) throws Exception {
        MybatisSqlSessionFactoryBean factoryBean = new MybatisSqlSessionFactoryBean();
        factoryBean.setDataSource(dataSource);
        // 指定实体类包(可选,MyBatis-Plus 自动扫描)
        factoryBean.setTypeAliasesPackage("com.example.entity.pg");
        // 配置 MyBatis-Plus 插件(分页等)
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        factoryBean.setPlugins(interceptor);
        return factoryBean.getObject();
    }

    @Primary
    @Bean(name = "pgTransactionManager")
    public DataSourceTransactionManager pgTransactionManager(@Qualifier("pgDataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Primary
    @Bean(name = "pgSqlSessionTemplate")
    public SqlSessionTemplate pgSqlSessionTemplate(@Qualifier("pgSqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}

2. 次数据源配置(SQL Server)

java 复制代码
package com.example.config;

import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionTemplate;
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;

@Configuration
@MapperScan(basePackages = "com.example.mapper.sqlserver",   // 指定次数据源的 Mapper 包
            sqlSessionFactoryRef = "sqlserverSqlSessionFactory")
public class SqlServerDataSourceConfig {

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

    @Bean(name = "sqlserverSqlSessionFactory")
    public SqlSessionFactory sqlserverSqlSessionFactory(@Qualifier("sqlserverDataSource") DataSource dataSource) throws Exception {
        MybatisSqlSessionFactoryBean factoryBean = new MybatisSqlSessionFactoryBean();
        factoryBean.setDataSource(dataSource);
        factoryBean.setTypeAliasesPackage("com.example.entity.sqlserver");
        // 分页插件
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        factoryBean.setPlugins(interceptor);
        return factoryBean.getObject();
    }

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

    @Bean(name = "sqlserverSqlSessionTemplate")
    public SqlSessionTemplate sqlserverSqlSessionTemplate(@Qualifier("sqlserverSqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}

四、使用示例(Service 层)

在 Service 中注入对应的 Mapper 即可,Spring 会自动根据包扫描区分使用哪个数据源。

java 复制代码
package com.example.service;

import com.example.mapper.pg.UserMapper;
import com.example.mapper.sqlserver.OrderMapper;
import com.example.entity.pg.User;
import com.example.entity.sqlserver.Order;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class BusinessService {

    @Autowired
    private UserMapper userMapper;       // 操作 PostgreSQL
    @Autowired
    private OrderMapper orderMapper;     // 操作 SQL Server

    // 各自独立的事务(分别提交或回滚)
    public void insertUser(User user) {
        userMapper.insert(user);
        orderMapper.list();
    }

    public void insertOrder(Order order) {
        orderMapper.insert(order);
    }

    // 如需跨数据源事务,需引入分布式事务(如 JTA,此处不展开)
}

五、注意事项

  1. MyBatis-Plus 插件 :若需要分页、乐观锁等插件,必须在每个数据源的 SqlSessionFactory 中单独配置 MybatisPlusInterceptor
  2. Mapper 扫描 :通过 @MapperScan 指定不同的 Mapper 包,确保两个数据源不会混淆。
  3. 事务管理@Transactional 默认使用主数据源的事务管理器。如果要对次数据源进行事务管理,可以在注解中指定 transactionManager,例如 @Transactional(transactionManager = "sqlserverTransactionManager")。跨多个数据源的事务需要分布式事务(如 Atomikos、Seata)支持。
  4. 实体类路径 :如果实体类不在 typeAliasesPackage 中,MyBatis-Plus 无法自动识别,可手动指定或使用 @TableName 全限定名。
  5. 连接池 :Spring Boot 默认使用 HikariCP,每个数据源独立连接池,可根据需要配置连接池参数