Springboot连接多数据源(MySQL&Oracle)

在实际开发中,我们经常会遇到需要同时操作多个数据库的场景,比如一部分数据存储在MySQL中,另一部分数据存储在Oracle中。本文将详细介绍如何在Spring Boot项目中配置并使用MySQL和Oracle两种不同的数据源。

一、准备工作:添加依赖

首先,我们需要在pom.xml中添加MySQL和Oracle的数据库连接依赖,以及相关的持久层框架依赖。

xml 复制代码
<!--MySQL连接驱动-->
<dependency>
    <groupId>com.mysql</groupId>
    <artifactId>mysql-connector-j</artifactId>
    <version>8.4.0</version>
    <scope>runtime</scope>
</dependency>

<!--Oracle连接驱动-->
<dependency>
    <groupId>com.oracle.database.jdbc</groupId>
    <artifactId>ojdbc11</artifactId>
    <version>23.9.0.25.07</version>
</dependency>

<!--MyBatis-Plus依赖(根据实际使用的持久层框架添加)-->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.3.1</version>
</dependency>

<!--Druid连接池依赖-->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.2.16</version>
</dependency>

注意:ojdbc的版本需要与JDK版本匹配,本文使用的ojdbc11对应Java 11,各位可以根据自己的JDK版本选择合适的ojdbc版本(如ojdbc8对应Java 8)。

二、配置数据源信息

application.yml(或application.properties)中配置两个数据源的连接信息,分别为MySQL和Oracle:

yaml 复制代码
spring:
  datasource:
    mysql-datasource:
      type: com.alibaba.druid.pool.DruidDataSource
      url: jdbc:mysql://localhost:3306/test?Unicode=true&characterEncoding=utf8&characterSetResults=utf8&allowMultiQueries=true&autoReconnect=true&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
      username: admin
      password: admin123
      driver-class-name: com.mysql.cj.jdbc.Driver
    oracle-datasource:
      type: com.alibaba.druid.pool.DruidDataSource
      ## 使用 SID 格式
      url: jdbc:oracle:thin:@localhost:1522:FREE
      username: test1
      password: test1_2025
      driver-class-name: oracle.jdbc.OracleDriver

配置说明:

  • 分别为两个数据源指定了不同的前缀:mysql-datasourceoracle-datasource
  • 配置了连接池类型为Druid
  • 包含了数据库连接的URL、用户名、密码和驱动类名
  • MySQL的URL中指定了时区、字符编码等参数
  • Oracle的URL使用了SID格式(@主机:端口:SID

三、配置数据源相关Bean

接下来,我们需要为每个数据源创建对应的配置类,包括数据源对象、事务管理器、SqlSessionFactory等。

1. MySQL数据源配置

java 复制代码
@Configuration
@MapperScan(
    basePackages = "com.lee.test.dao",  // MySQL对应的Mapper接口所在包
    sqlSessionFactoryRef = "sqlSessionFactory"  // 指定使用的SqlSessionFactory
)
public class MysqlConfig {

    @Value("${spring.datasource.mysql-datasource.url}")
    private String url;

    @Value("${spring.datasource.mysql-datasource.username}")
    private String username;

    @Value("${spring.datasource.mysql-datasource.password}")
    private String password;

    @Value("${spring.datasource.mysql-datasource.driver-class-name}")
    private String driverClassName;

    /**
     * 配置MySQL数据源
     * @Primary 注解指定该数据源为默认数据源
     */
    @Primary
    @Bean(name = "dataSource")
    public DataSource dataSource(){
        DruidDataSource dataSource = DataSourceBuilder.create().type(DruidDataSource.class).build();
        dataSource.setUrl(url);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        dataSource.setDriverClassName(driverClassName);
        dataSource.setDbType(DbType.MYSQL.getDb());
        return dataSource;
    }

    /**
     * 配置MySQL事务管理器
     */
    @Bean(name = "transactionManager")
    public DataSourceTransactionManager transactionManager(@Qualifier("dataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    /**
     * 配置MySQL的SqlSessionFactory
     */
    @Bean(name = "sqlSessionFactory")
    public MybatisSqlSessionFactoryBean createSqlSessionFactory(@Qualifier("dataSource") DataSource dataSource) throws IOException {
        MybatisSqlSessionFactoryBean sqlSessionFactoryBean = new MybatisSqlSessionFactoryBean();
        // 设置MyBatis配置文件的路径
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        // 设置mapper对应的XML文件的路径
        sqlSessionFactoryBean.setMapperLocations(resolver.getResources("classpath*:mappers/**/*.xml"));
        // 设置数据源
        sqlSessionFactoryBean.setDataSource(dataSource);
        // 设置mapper接口所在的包(用于类型别名)
        sqlSessionFactoryBean.setTypeAliasesPackage("com.lee.test.dao.mapper.*");
        // 可以添加MyBatis插件,如分页插件等
        // sqlSessionFactoryBean.setPlugins();
        return sqlSessionFactoryBean;
    }

    /**
     * 配置MySQL的MyBatis-Plus插件
     */
    @Bean(name = "mybatisPlusInterceptor")
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        // 分页插件,指定数据库类型为MySQL
        PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);
        paginationInnerInterceptor.setOptimizeJoin(true);
        // 设置查询分页最大限制
        paginationInnerInterceptor.setMaxLimit(500L);
        interceptor.addInnerInterceptor(paginationInnerInterceptor);
        return interceptor;
    }

}

2. Oracle数据源配置

java 复制代码
@Configuration
@MapperScan(
    basePackages = "com.lee.test.ora",  // Oracle对应的Mapper接口所在包
    sqlSessionFactoryRef = "oracleSqlSessionFactory"  // 指定使用的SqlSessionFactory
)
public class OracleConfig {

    @Value("${spring.datasource.oracle-datasource.url}")
    private String url;

    @Value("${spring.datasource.oracle-datasource.username}")
    private String username;

    @Value("${spring.datasource.oracle-datasource.password}")
    private String password;

    @Value("${spring.datasource.oracle-datasource.driver-class-name}")
    private String driverClassName;

    /**
     * 配置Oracle数据源
     */
    @Bean(name = "oracleDataSource")
    public DataSource oracleDataSource(){
        DruidDataSource dataSource = DataSourceBuilder.create().type(DruidDataSource.class).build();
        dataSource.setUrl(url);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        dataSource.setDriverClassName(driverClassName);
        dataSource.setDbType(DbType.ORACLE_12C.getDb());
        // Oracle需要设置验证查询语句
        dataSource.setValidationQuery("SELECT 1 FROM DUAL");
        return dataSource;
    }

    /**
     * 配置Oracle事务管理器
     */
    @Bean(name = "oracleTransactionManager")
    public DataSourceTransactionManager oracleTransactionManager(@Qualifier("oracleDataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    /**
     * 配置Oracle的SqlSessionFactory
     */
    @Bean(name = "oracleSqlSessionFactory")
    public MybatisSqlSessionFactoryBean oracleSqlSessionFactory(@Qualifier("oracleDataSource") DataSource dataSource) throws IOException {
        MybatisSqlSessionFactoryBean sqlSessionFactoryBean = new MybatisSqlSessionFactoryBean();
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        // 设置mapper对应的XML文件的路径
        sqlSessionFactoryBean.setMapperLocations(resolver.getResources("classpath*:mappers/**/*.xml"));
        // 设置数据源
        sqlSessionFactoryBean.setDataSource(dataSource);
        // 设置mapper接口所在的包
        sqlSessionFactoryBean.setTypeAliasesPackage("com.lee.test.ora.mapper.*");
        // 可以添加MyBatis插件
        // sqlSessionFactoryBean.setPlugins();
        return sqlSessionFactoryBean;
    }

    /**
     * 配置Oracle的MyBatis-Plus插件
     */
    @Bean(name = "oracleMybatisPlusInterceptor")
    public MybatisPlusInterceptor oracleMybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        // 分页插件,指定数据库类型为Oracle 12c
        PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.ORACLE_12C);
        paginationInnerInterceptor.setOptimizeJoin(true);
        paginationInnerInterceptor.setMaxLimit(500L);
        interceptor.addInnerInterceptor(paginationInnerInterceptor);
        return interceptor;
    }

}

四、关键配置细节说明

  1. 包路径分离

    • MySQL的Mapper接口放在com.lee.test.dao包下
    • Oracle的Mapper接口放在com.lee.test.ora包下
    • 通过@MapperScan注解的basePackages属性指定各自扫描的包路径,实现数据源与Mapper的绑定
  2. SqlSessionFactory区分

    • 两个数据源分别配置了不同的SqlSessionFactorysqlSessionFactoryoracleSqlSessionFactory
    • @MapperScan注解中通过sqlSessionFactoryRef属性指定对应的SqlSessionFactory
  3. 数据源标识

    • 为每个数据源的Bean指定了唯一的名称(如dataSourceoracleDataSource
    • 使用@Qualifier注解在注入时指定具体的数据源
  4. 默认数据源

    • 通过@Primary注解指定MySQL为默认数据源,当不指定数据源时会使用该默认数据源
  5. 数据库类型适配

    • 两种数据源分别设置了对应的数据库类型(DbType.MYSQLDbType.ORACLE_12C
    • 分页插件也根据数据库类型进行了适配,确保分页查询正确执行
  6. Oracle特殊配置

    • Oracle需要设置验证查询语句:SELECT 1 FROM DUAL
    • URL格式与MySQL不同,使用了Oracle特有的SID格式

五、接口验证

配置完成后,我们可以编写一个测试控制器来验证多数据源是否配置成功:

java 复制代码
@Slf4j
@RestController
@RequestMapping("/v1/test")
@Api(tags = "测试")
public class TestController {

    // 注入MySQL对应的Service
    @Resource
    private UserService userService;
    
    // 注入Oracle对应的Service
    @Resource
    private ZdZzglXzjgService zdZzglXzjgService;

    /**
     * 测试查询MySQL数据
     */
    @GetMapping("/queryUserByPhone")
    public UserDTO findByPhone(String phone) {
        if (StringUtils.isEmpty(phone)){
            return null;
        }
        return userService.findByPhone(phone);
    }

    /**
     * 测试查询Oracle数据
     */
    @GetMapping("/queryByDwdm")
    public ZdZzglXzjg queryByDwdm(String dwdm) {
        if (StringUtils.isEmpty(dwdm)){
            return null;
        }
        return zdZzglXzjgService.queryByDwdm(dwdm);
    }
}

使用方法:

  1. UserService及其实现类中注入的是MySQL对应的Mapper(位于com.lee.test.dao包下)
  2. ZdZzglXzjgService及其实现类中注入的是Oracle对应的Mapper(位于com.lee.test.ora包下)
  3. 调用不同的接口方法,分别操作不同的数据库

六、总结

通过本文的配置,我们实现了Spring Boot项目同时连接MySQL和Oracle两种数据源的功能。关键在于:

  1. 正确配置多数据源的连接信息
  2. 为每个数据源创建独立的配置类,包括数据源、事务管理器和SqlSessionFactory
  3. 通过包路径分离和@MapperScan注解实现Mapper与数据源的绑定
  4. 注意不同数据库的特性差异,进行针对性配置

这种方式适用于需要同时操作多个不同类型数据库的场景,配置清晰,易于维护。如果需要添加更多数据源,只需按照相同的模式新增配置类即可。

相关推荐
潇凝子潇3 小时前
MySQL Redo Log 和 Undo Log 满了会有什么问题
数据库·mysql
周杰伦_Jay5 小时前
【Homebrew安装 MySQL 】macOS 用 Homebrew 安装 MySQL 完整教程
数据库·mysql·macos
贝多芬也爱敲代码12 小时前
如何减小ES和mysql的同步时间差
大数据·mysql·elasticsearch
安当加密12 小时前
MySQL数据库透明加密(TDE)解决方案:基于国密SM4的合规与性能优化实践
数据库·mysql·性能优化
007php00713 小时前
某大厂跳动面试:计算机网络相关问题解析与总结
java·开发语言·学习·计算机网络·mysql·面试·职场和发展
JH307313 小时前
第七篇:Buffer Pool 与 InnoDB 其他组件的协作
java·数据库·mysql·oracle
数据库生产实战13 小时前
解析Oracle 19C中并行INSERT SELECT的工作原理
数据库·oracle
阿沁QWQ14 小时前
MySQL服务器配置与管理
服务器·数据库·mysql