Spring Boot 2.2.6 Java应用SQL查询错误连接数据库的偶发构建异常排查求助
嘿,你遇到的这个问题确实挺棘手的——双数据源下特定查询偶尔错连Postgres,还和构建产物绑定,重启也没法解决。不过仔细看了你贴的代码,我发现了几个关键的配置错误,这应该就是问题的核心:
1. @EnableJpaRepositories引用的Bean名称不匹配
你的OrganizerDatasourceConfiguration类上的@EnableJpaRepositories注解写了:
@EnableJpaRepositories(entityManagerFactoryRef = "entityManagerFactoryRef", transactionManagerRef = "transactionManagerRef", ...)
但你实际定义的EntityManagerFactory Bean叫zzzEntityManagerFactory,事务管理器Bean叫zzzTransactionManager——这俩名字完全对不上啊!
当Spring找不到你指定的entityManagerFactoryRef和transactionManagerRef时,它会自动 fallback 到标记了@Primary的数据源相关Bean(也就是你的Postgres数据源,因为它应该是默认的主数据源)。至于为什么构建产物会出现“要么全对要么全错”的情况?这大概率是因为构建过程中类路径扫描的顺序偶尔出现波动,有时候Spring能“碰巧”找到匹配的Bean,但大多数时候都会回退到主数据源,导致查询错误连接到Postgres。
2. Repository的事务管理器名称不匹配
再看你的OpportunityPaymentInstallmentRepository,事务注解里指定的是:
@Transactional(value = "organizerTransactionManager", ...)
但你配置类里的事务管理器Bean明明叫zzzTransactionManager,名称完全不匹配!这会导致Spring找不到指定的事务管理器,只能用默认的主事务管理器,最终用Postgres数据源执行本该发往MSSQL的查询,自然就会报relation "dbo.sometable" does not exist(因为Postgres里没有MSSQL的dbo schema和对应表)。
具体修复步骤
第一步:修正@EnableJpaRepositories的引用名称
把配置类上的注解改成和你实际定义的Bean名称一致:
@EnableJpaRepositories( entityManagerFactoryRef = "zzzEntityManagerFactory", transactionManagerRef = "zzzTransactionManager", basePackages = { "com.xxx.consumers.handlers.payment.provider.xxx.repository" } )
第二步:修正Repository的事务管理器名称
把Repository里的@Transactional注解的value改成正确的事务管理器Bean名称:
@Transactional(value = "zzzTransactionManager", readOnly = true, propagation = Propagation.REQUIRES_NEW) Optional<OpportunityPaymentInstallment> getByPaymentInstallmentId(Long paymentInstallmentId);
第三步:确保数据源扫描范围不重叠
检查你的Postgres数据源配置类,确保它的@EnableJpaRepositories指定了专属的Repository包路径,只扫描属于Postgres的Repository,避免和MSSQL的Repository扫描范围重叠。比如Postgres的配置类应该类似:
@Primary @Configuration @EnableJpaRepositories( entityManagerFactoryRef = "postgresEntityManagerFactory", transactionManagerRef = "postgresTransactionManager", basePackages = { "com.xxx.consumers.postgres.repository" } // 只扫Postgres的Repository ) public class PostgresDatasourceConfiguration { // 对应的数据源、EntityManagerFactory、事务管理器配置,记得标记@Primary }
第四步:确认@Primary标记的正确性
因为你有两个数据源,必须确保其中一个(通常是Postgres)被标记为@Primary,而MSSQL的相关Bean(数据源、EntityManagerFactory、事务管理器)不要标记@Primary。这样当Spring需要默认Bean时会用主数据源,而你的MSSQL相关Repository会通过明确的ref指定使用自己的Bean,不会出现混淆。
额外需要排查的点
- 检查你的application配置文件(application.yml/properties),确保MSSQL的
zzz.datasource配置(URL、用户名、密码)确实指向MSSQL,没有和Postgres的配置搞混。 - 构建镜像时,确认配置文件是正确打包进去的,没有出现构建脚本错误替换配置的情况(比如把MSSQL的配置换成了Postgres的)。
内容的提问来源于stack exchange,提问作者asegmen

