Spring Boot集成Spring R2DBC多数据源查询异常排查
我开发了一个连接fo_pgdb和if_pgdb两个Schema的Spring Boot服务,基于Spring R2DBC实现多数据源配置,但遇到如下异常:
- 查询
fo_pgdb的BID_LINES表中ID为123、345的记录可正常返回结果; - 查询
if_pgdb的BID_LINES表中ID为567、8910的记录返回空集,但这些ID在if_pgdb的对应表中实际存在; - 使用ID123、345查询
if_pgdb的BID_LINES表时,返回的却是fo_pgdb表中的对应记录。
已确认两个数据源的连接URL配置正确,请问可能的问题是什么?
@Configuration @EnableR2dbcRepositories(entityOperationsRef = "foEntityTemplate", basePackages = "com.r2dbc.poc.repository") public class FODatabaseConfig { //@Value("${spring.r2dbc.fo.connection.url}") private String url = "r2dbc:postgresql://username:password@database-dev-fo-css-rr-db.corp.com:1200/fo_pgdb"; @Bean @Qualifier("foConnectionFactory") public ConnectionFactory foConnectionFactory() { return ConnectionFactories.get(url); } @Bean public R2dbcEntityOperations foEntityTemplate(@Qualifier("foConnectionFactory") ConnectionFactory connectionFactory) { DefaultReactiveDataAccessStrategy strategy = new DefaultReactiveDataAccessStrategy(PostgresDialect.INSTANCE); DatabaseClient databaseClient = DatabaseClient.builder() .connectionFactory(connectionFactory) .bindMarkers(PostgresDialect.INSTANCE.getBindMarkersFactory()) .build(); return new R2dbcEntityTemplate(databaseClient, strategy); } } @Configuration @EnableR2dbcRepositories(entityOperationsRef = "ifEntityTemplate") public class IFDatabaseConfig { //@Value("${spring.r2dbc.if.connection.url}") private String url = "r2dbc:postgresql://username:password@database-blue-if-CSS-db.corp.com:1200/if_pgdb"; @Bean @Qualifier("ifConnectionFactory") public ConnectionFactory ifConnectionFactory() { return ConnectionFactories.get(url); } @Bean public R2dbcEntityOperations ifEntityTemplate(@Qualifier("ifConnectionFactory") ConnectionFactory connectionFactory) { DefaultReactiveDataAccessStrategy strategy = new DefaultReactiveDataAccessStrategy(PostgresDialect.INSTANCE); DatabaseClient databaseClient = DatabaseClient.builder() .connectionFactory(connectionFactory) .bindMarkers(PostgresDialect.INSTANCE.getBindMarkersFactory()) .build(); return new R2dbcEntityTemplate(databaseClient, strategy); } } @Service @RequiredArgsConstructor public class CrewMemberSchedulePeriodPaymentService { private final FOCrewMemberBidLineRepository foCrewMemberBidlineRepository; private final IFCrewMemberBidLineRepository ifCrewMemberBidLineRepository; public Flux<FOCrewMemberBidLine> getFOBidLines(List<Long> id) { return foCrewMemberBidlineRepository.findAllById(id); } public Flux<IFCrewMemberBidLine> getIFBidLines(List<Long> id) { return ifCrewMemberBidLineRepository.findAllById(id); } } @Repository public interface FOCrewMemberBidLineRepository extends R2dbcRepository<FOCrewMemberBidLine, Long> { @Override Flux<FOCrewMemberBidLine> findAllById(Iterable<Long> longs); } @Repository public interface IFCrewMemberBidLineRepository extends R2dbcRepository<IFCrewMemberBidLine, Long> { @Override Flux<IFCrewMemberBidLine> findAllById(Iterable<Long> longs); } @Table(value = "BID_LINES") @Builder @NoArgsConstructor @AllArgsConstructor @Data public class FOCrewMemberBidLine { @Id @Column(value = "bidlinseqnumber") private Long bidlinseqnumber; @Column(value = "bidlinschedperiod") private String bidlinschedperiod; } @Table(value = "BID_LINES") @Builder @NoArgsConstructor @AllArgsConstructor @Data public class IFCrewMemberBidLine { @Id @Column(value = "bidlinseqnumber") private Long bidlinseqnumber; @Column(value = "bidlinschedperiod") private String bidlinschedperiod; }
核心问题1:Repository未正确绑定对应数据源
IFDatabaseConfig类的@EnableR2dbcRepositories没有指定basePackages或basePackageClasses属性,导致Spring无法区分不同数据源对应的Repository。默认情况下,所有Repository都会使用第一个加载的数据源(即FO的数据源),这就解释了为什么查询IF的Repository却返回FO的数据。
修复方案:
给IFDatabaseConfig的@EnableR2dbcRepositories指定专属的包路径或Repository类,确保两个数据源的Repository被正确划分:
@Configuration @EnableR2dbcRepositories( entityOperationsRef = "ifEntityTemplate", basePackageClasses = IFCrewMemberBidLineRepository.class // 或者指定专属包如"com.r2dbc.poc.repository.if" ) public class IFDatabaseConfig { // ... 原有代码 }
同时建议给FODatabaseConfig的basePackages也做精准划分,比如指定com.r2dbc.poc.repository.fo,并将两个Repository分别放到对应子包下,避免范围重叠。
核心问题2:实体类未指定Schema
两个实体类的@Table注解仅指定了表名BID_LINES,未明确对应的Schema。当数据库存在多个Schema时,默认会使用连接用户的默认Schema,可能导致查询到错误Schema下的表。
修复方案:
在@Table注解中明确指定Schema:
// FO实体类 @Table(value = "BID_LINES", schema = "fo_pgdb") // ... 其他注解 // IF实体类 @Table(value = "BID_LINES", schema = "if_pgdb") // ... 其他注解
也可以在数据源URL中指定默认Schema(但更推荐在实体类上明确指定,避免数据源配置与实体耦合):
比如FO的URL改为:r2dbc:postgresql://username:password@database-dev-fo-css-rr-db.corp.com:1200/fo_pgdb?currentSchema=fo_pgdb
额外验证点
- 确认两个数据源的连接用户拥有对应Schema的查询权限;
- 配置
logging.level.org.springframework.r2dbc=DEBUG打印SQL日志,验证实际执行的SQL是否查询了正确的Schema和表。
内容的提问来源于stack exchange,提问作者Tony Neves

