🎉 Nanko's Log has been deployed. Read more →
PostsArchiveTags

Spring Boot and MyBatis Multiple DataSource Configuration

Mr Nanko,

在生产环境中,我们经常需要配置多个数据源来连接不同的数据库。本文介绍如何在 Spring Boot 和 MyBatis 项目中配置 MySQL 和 Oracle 双数据源,包括完整的配置步骤和常见问题解决方案。

Table of Contents

项目环境

配置步骤

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: NULL

3. 创建数据源配置类

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 接口找不到

原因

解决方案

问题 4:事务不生效

原因:没有指定正确的事务管理器。

解决方案:在 Service 方法上使用 @Transactional 并指定事务管理器:

@Transactional(transactionManager = "mysqlTransactionManager") public void mysqlTransaction() { // MySQL 事务操作 } @Transactional(transactionManager = "oracleTransactionManager") public void oracleTransaction() { // Oracle 事务操作 }

参考

  1. 实战指南,SpringBoot + Mybatis 如何对接多数据源 
  2. Spring boot+Mybatis连接多种数据库oracle,mysql,sqlserver 
  3. SpringBoot+MyBatis项目中同时操作多个数据库 
© 2026 Mr Nanko. CC BY-NC 4.0