在实际开发中,我们经常会遇到需要同时操作多个数据库的场景,比如一部分数据存储在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-datasource
和oracle-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;
}
}
四、关键配置细节说明
-
包路径分离:
- MySQL的Mapper接口放在
com.lee.test.dao
包下 - Oracle的Mapper接口放在
com.lee.test.ora
包下 - 通过
@MapperScan
注解的basePackages
属性指定各自扫描的包路径,实现数据源与Mapper的绑定
- MySQL的Mapper接口放在
-
SqlSessionFactory区分:
- 两个数据源分别配置了不同的
SqlSessionFactory
(sqlSessionFactory
和oracleSqlSessionFactory
) - 在
@MapperScan
注解中通过sqlSessionFactoryRef
属性指定对应的SqlSessionFactory
- 两个数据源分别配置了不同的
-
数据源标识:
- 为每个数据源的Bean指定了唯一的名称(如
dataSource
和oracleDataSource
) - 使用
@Qualifier
注解在注入时指定具体的数据源
- 为每个数据源的Bean指定了唯一的名称(如
-
默认数据源:
- 通过
@Primary
注解指定MySQL为默认数据源,当不指定数据源时会使用该默认数据源
- 通过
-
数据库类型适配:
- 两种数据源分别设置了对应的数据库类型(
DbType.MYSQL
和DbType.ORACLE_12C
) - 分页插件也根据数据库类型进行了适配,确保分页查询正确执行
- 两种数据源分别设置了对应的数据库类型(
-
Oracle特殊配置:
- Oracle需要设置验证查询语句:
SELECT 1 FROM DUAL
- URL格式与MySQL不同,使用了Oracle特有的SID格式
- Oracle需要设置验证查询语句:
五、接口验证
配置完成后,我们可以编写一个测试控制器来验证多数据源是否配置成功:
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);
}
}
使用方法:
UserService
及其实现类中注入的是MySQL对应的Mapper(位于com.lee.test.dao
包下)ZdZzglXzjgService
及其实现类中注入的是Oracle对应的Mapper(位于com.lee.test.ora
包下)- 调用不同的接口方法,分别操作不同的数据库
六、总结
通过本文的配置,我们实现了Spring Boot项目同时连接MySQL和Oracle两种数据源的功能。关键在于:
- 正确配置多数据源的连接信息
- 为每个数据源创建独立的配置类,包括数据源、事务管理器和SqlSessionFactory
- 通过包路径分离和
@MapperScan
注解实现Mapper与数据源的绑定 - 注意不同数据库的特性差异,进行针对性配置
这种方式适用于需要同时操作多个不同类型数据库的场景,配置清晰,易于维护。如果需要添加更多数据源,只需按照相同的模式新增配置类即可。