Springboot 实现多数据源(PostgreSQL 和 SQL Server)连接
💡 作者:古渡蓝按
个人微信公众号 :微信公众号(深入浅出谈java)
感觉本篇对你有帮助可以关注一下,会不定期更新知识和面试资料、技巧!!!
在 Spring Boot 中同时连接 PostgreSQL 和 SQL Server 两个数据库,并结合 MyBatis-Plus 进行 ORM 操作,通常需要配置多数据源。以下提供一个完整的配置方案,包括依赖、配置文件、数据源配置类、MyBatis-Plus 集成以及使用示例
本次就以 PostgreSQL 和 SQL 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,此处不展开)
}
五、注意事项
- MyBatis-Plus 插件 :若需要分页、乐观锁等插件,必须在每个数据源的
SqlSessionFactory中单独配置MybatisPlusInterceptor。 - Mapper 扫描 :通过
@MapperScan指定不同的 Mapper 包,确保两个数据源不会混淆。 - 事务管理 :
@Transactional默认使用主数据源的事务管理器。如果要对次数据源进行事务管理,可以在注解中指定transactionManager,例如@Transactional(transactionManager = "sqlserverTransactionManager")。跨多个数据源的事务需要分布式事务(如 Atomikos、Seata)支持。 - 实体类路径 :如果实体类不在
typeAliasesPackage中,MyBatis-Plus 无法自动识别,可手动指定或使用@TableName全限定名。 - 连接池 :Spring Boot 默认使用 HikariCP,每个数据源独立连接池,可根据需要配置连接池参数