spring boot 3 配置 oracle 多数据源的核心难点是 ojdbc8 兼容性、abstractroutingdatasource 线程上下文穿透、mybatis 多 sqlsessionfactory 实例绑定;配错任一环节会导致静默走默认库或 nouniquebeandefinitionexception。

Spring Boot 3 配置 Oracle 多数据源,核心难点不在“能不能配”,而在于 ojdbc8 兼容性、AbstractRoutingDataSource 的线程上下文穿透、以及 MyBatis 多 SqlSessionFactory 实例绑定这三处——配错任意一个,都会静默走默认库或抛 NoUniqueBeanDefinitionException。
driver-class-name 和 ojdbc8 版本必须严格匹配
Spring Boot 3 默认基于 Jakarta EE 9+,要求 JDBC 驱动必须支持 javax.sql.DataSource(非 java.sql.DataSource)语义,且驱动类名不能写错:
-
oracle.jdbc.driver.OracleDriver已废弃,启动时会警告但可能不报错;必须用oracle.jdbc.OracleDriver(注意没有.driver) -
ojdbc8必须选com.oracle.database.jdbc:ojdbc8:21.12.0.0或更高(对应 Oracle 21c/19c),低于21.1.0.0在 TLS 1.3 环境下 handshake 失败 - URL 中务必带
?oracle.net.disableOob=true,否则高并发下连接随机中断,现象是Socket read timed out且无堆栈
application.yml 缩进和 prefix 绑定极易失效
Spring Boot 3 的 @ConfigurationProperties 对 YAML 层级极其敏感,缩进错一位就会导致 bindingResult.hasErrors() == true 且静默 fallback 到 Hikari 默认配置:
- 每个数据源的
url、username、password、driver-class-name必须与spring.datasource.db1同级对齐(即四个空格或两个空格,但全文统一) - prefix 必须精确到字段层,例如
@ConfigurationProperties("spring.datasource.db1"),不能漏掉db1;若写成"spring.datasource",则所有 db1/db2 配置会被合并覆盖 - 不要用
spring.datasource.type指定 Hikari 类名,Boot 3 自动识别;手动指定反而触发BeanCreationException
MyBatis 多 SqlSessionFactory 必须显式隔离
Spring Boot 3 + MyBatis Starter 不再自动注册多个 SqlSessionFactory,必须为每个 Oracle 数据源手动生成并绑定独立的 @MapperScan:
- 每个
@Bean的SqlSessionFactory必须传入对应数据源实例,例如new SqlSessionFactoryBean().setDataSource(db1DataSource) -
@MapperScan的basePackages和sqlSessionFactoryRef必须一一对应,例如@MapperScan(basePackages = "com.example.mapper.db1", sqlSessionFactoryRef = "sqlSessionFactoryDb1") - 切忌共用同一个
SqlSessionTemplate或让MapperScannerConfigurer扫描重叠包路径,否则出现 “Mapper method not found” 或 “all queries go to db1”
DynamicDataSource 切换时 null 值不会报错,但会 fallback
AbstractRoutingDataSource.determineCurrentLookupKey() 返回 null 是合法行为,它会直接使用 setDefaultTargetDataSource() 设置的默认源——这不是 bug,是设计逻辑,但常被误判为“切换失败”:
- 确保
DataSourceUtil.setDB("db2")在 DAO 调用前执行,且不能在finally块里调用clear()后又执行数据库操作 - AOP 切面中,子 Service 方法若未加
@DS("db2")注解,将沿用父方法的数据源,不会自动继承;嵌套调用必须显式标注 - 事务方法内切换数据源会导致
TransactionSynchronizationManager.getResource()缓存错乱,建议切换只发生在 service 外层,避免事务传播干扰
最易忽略的是:Spring Boot 3 的 DataSourceTransactionManager 无法跨数据源管理事务,@Transactional 只能绑定单个 PlatformTransactionManager Bean;若需跨 Oracle 库事务,得上 XA 或业务层补偿,别指望配置能解决。











