CTRL K
Spring Boot and MyBatis Multiple DataSource Configuration
Mr Nanko,
在生产环境中,我们经常需要配置多个数据源来连接不同的数据库。本文介绍如何在 Spring Boot 和 MyBatis 项目中配置 MySQL 和 Oracle 双数据源,包括完整的配置步骤和常见问题解决方案。
Table of Contents
项目环境
- Spring Boot 2.5.2
- MyBatis Spring Boot Starter 2.3.0
- MySQL 8.x
- Oracle 11g
- PageHelper 1.4.6(分页插件)
配置步骤
1. 添加 Maven 依赖
在 pom.xml 中添加必要的依赖:
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc6</artifactId>
<version>11.2.0.4</version>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.4.6</version>
</dependency>2. 配置 application.yml
配置文件中定义多个数据源的连接信息。注意:使用 jdbc-url 而不是 url。
spring:
application:
name: demo
datasource:
# MySQL 数据源配置
mysql:
jdbc-url: jdbc:mysql://127.0.0.1:3306/demo?serverTimezone=Asia/Shanghai&useSSL=false&useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&allowMultiQueries=true
username: root
password: password
driver-class-name: com.mysql.cj.jdbc.Driver
# Oracle 数据源配置
oracle:
jdbc-url: jdbc:oracle:thin:@127.0.0.1:1521:EX
username: root
password: password
driver-class-name: oracle.jdbc.OracleDriver
mybatis:
mapper-locations: classpath*:mybatis/**/**.xml
configuration:
jdbc-type-for-null: NULL3. 创建数据源配置类
3.1 MySQL 数据源配置(主数据源)
创建 MySQL 数据源配置类,使用 @Primary 注解标记为主数据源:
package app.nanko.demo.config;
import com.github.pagehelper.PageInterceptor;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
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.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import javax.sql.DataSource;
import java.util.Properties;
@Configuration
@MapperScan(basePackages = "app.nanko.demo.mapper.mysql", sqlSessionFactoryRef = "mysqlSqlSessionFactory")
public class MySQLDataSourceConfig {
/**
* 创建 MySQL 数据源
*/
@Primary
@Bean(name = "mysqlDataSource")
@ConfigurationProperties(prefix = "spring.datasource.mysql")
public DataSource mysqlDataSource() {
return DataSourceBuilder.create().build();
}
/**
* 创建 MySQL SqlSessionFactory
*/
@Primary
@Bean(name = "mysqlSqlSessionFactory")
public SqlSessionFactory mysqlSqlSessionFactory(@Qualifier("mysqlDataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
// 设置 Mapper XML 文件路径
sqlSessionFactoryBean.setMapperLocations(
new PathMatchingResourcePatternResolver().getResources("classpath*:mybatis/mysql/**.xml")
);
// 添加分页插件
sqlSessionFactoryBean.setPlugins(new Interceptor[]{pageInterceptor()});
return sqlSessionFactoryBean.getObject();
}
/**
* 创建 MySQL 事务管理器
*/
@Primary
@Bean(name = "mysqlTransactionManager")
public DataSourceTransactionManager mysqlTransactionManager(@Qualifier("mysqlDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
/**
* 创建 MySQL SqlSessionTemplate
*/
@Primary
@Bean(name = "mysqlSqlSessionTemplate")
public SqlSessionTemplate mysqlSqlSessionTemplate(@Qualifier("mysqlSqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
/**
* 配置 MySQL 分页插件
*/
private PageInterceptor pageInterceptor() {
PageInterceptor pageInterceptor = new PageInterceptor();
Properties properties = new Properties();
properties.setProperty("helperDialect", "mysql");
properties.setProperty("reasonable", "true");
pageInterceptor.setProperties(properties);
return pageInterceptor;
}
}3.2 Oracle 数据源配置
创建 Oracle 数据源配置类:
package app.nanko.demo.config;
import com.github.pagehelper.PageInterceptor;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
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.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import javax.sql.DataSource;
import java.util.Properties;
@Configuration
@MapperScan(basePackages = "app.nanko.demo.mapper.oracle", sqlSessionFactoryRef = "oracleSqlSessionFactory")
public class OracleDataSourceConfig {
/**
* 创建 Oracle 数据源
*/
@Bean(name = "oracleDataSource")
@ConfigurationProperties(prefix = "spring.datasource.oracle")
public DataSource oracleDataSource() {
return DataSourceBuilder.create().build();
}
/**
* 创建 Oracle SqlSessionFactory
*/
@Bean(name = "oracleSqlSessionFactory")
public SqlSessionFactory oracleSqlSessionFactory(@Qualifier("oracleDataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
// 设置 Mapper XML 文件路径
sqlSessionFactoryBean.setMapperLocations(
new PathMatchingResourcePatternResolver().getResources("classpath*:mybatis/oracle/**.xml")
);
// 添加分页插件
sqlSessionFactoryBean.setPlugins(new Interceptor[]{pageInterceptor()});
return sqlSessionFactoryBean.getObject();
}
/**
* 创建 Oracle 事务管理器
*/
@Bean(name = "oracleTransactionManager")
public DataSourceTransactionManager oracleTransactionManager(@Qualifier("oracleDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
/**
* 创建 Oracle SqlSessionTemplate
*/
@Bean(name = "oracleSqlSessionTemplate")
public SqlSessionTemplate oracleSqlSessionTemplate(@Qualifier("oracleSqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
/**
* 配置 Oracle 分页插件
*/
private PageInterceptor pageInterceptor() {
PageInterceptor pageInterceptor = new PageInterceptor();
Properties properties = new Properties();
properties.setProperty("helperDialect", "oracle");
properties.setProperty("reasonable", "true");
pageInterceptor.setProperties(properties);
return pageInterceptor;
}
}4. 修改启动类
启动类需要排除数据源自动配置:
package app.nanko.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}项目结构示例
src/main/java/
└── app/nanko/demo/
├── config/
│ ├── MySQLDataSourceConfig.java # MySQL 数据源配置
│ └── OracleDataSourceConfig.java # Oracle 数据源配置
├── mapper/
│ ├── mysql/
│ │ └── UserMapper.java # MySQL Mapper 接口
│ └── oracle/
│ └── OrderMapper.java # Oracle Mapper 接口
├── entity/
│ ├── User.java
│ └── Order.java
└── DemoApplication.java
src/main/resources/
├── application.yml
└── mybatis/
├── mysql/
│ └── UserMapper.xml # MySQL Mapper XML
└── oracle/
└── OrderMapper.xml # Oracle Mapper XML使用示例
Mapper 接口示例
MySQL Mapper 接口:
package app.nanko.demo.mapper.mysql;
import app.nanko.demo.entity.User;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface UserMapper {
List<User> selectAll();
User selectById(Long id);
}Oracle Mapper 接口:
package app.nanko.demo.mapper.oracle;
import app.nanko.demo.entity.Order;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface OrderMapper {
List<Order> selectAll();
Order selectById(Long id);
}Service 层使用
package app.nanko.demo.service;
import app.nanko.demo.entity.Order;
import app.nanko.demo.entity.User;
import app.nanko.demo.mapper.mysql.UserMapper;
import app.nanko.demo.mapper.oracle.OrderMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class DemoService {
@Autowired
private UserMapper userMapper; // 使用 MySQL 数据源
@Autowired
private OrderMapper orderMapper; // 使用 Oracle 数据源
public void businessLogic() {
// 查询 MySQL 数据
User user = userMapper.selectById(1L);
// 查询 Oracle 数据
Order order = orderMapper.selectById(1001L);
// 业务逻辑处理...
}
}常见问题
问题 1:jdbcUrl is required with driverClassName
原因:Spring Boot 2.x 使用 Hikari 连接池,配置字段必须使用 jdbc-url 而非 url。
解决方案:在 application.yml 中使用 jdbc-url 配置数据库连接地址。
spring:
datasource:
mysql:
jdbc-url: jdbc:mysql://... # 正确
# url: jdbc:mysql://... # 错误问题 2:多个数据源时必须指定主数据源
原因:Spring Boot 需要知道哪个是默认数据源。
解决方案:在其中一个数据源配置类的所有 Bean 上添加 @Primary 注解。
问题 3:Mapper 接口找不到
原因:
@MapperScan的basePackages配置错误- Mapper XML 文件路径配置错误
解决方案:
- 检查
@MapperScan的包路径是否正确 - 检查
setMapperLocations的路径是否与实际文件路径匹配
问题 4:事务不生效
原因:没有指定正确的事务管理器。
解决方案:在 Service 方法上使用 @Transactional 并指定事务管理器:
@Transactional(transactionManager = "mysqlTransactionManager")
public void mysqlTransaction() {
// MySQL 事务操作
}
@Transactional(transactionManager = "oracleTransactionManager")
public void oracleTransaction() {
// Oracle 事务操作
}参考
- 实战指南,SpringBoot + Mybatis 如何对接多数据源
- Spring boot+Mybatis连接多种数据库oracle,mysql,sqlserver
- SpringBoot+MyBatis项目中同时操作多个数据库
© 2026 Mr Nanko. CC BY-NC 4.0