Spring Boot多数据库配置问题:Repository误用主数据库
解决Spring Boot多数据源下Repository始终复用主库的问题
你的核心问题是非主库的Repository没有被正确绑定到对应的数据源,导致调用接口时始终走主库(apex),而目标库中没有user表,因此抛出SQLSyntaxErrorException。以下是针对性的排查和修复步骤:
1. 修正数据源配置类的关键绑定
每个独立数据源必须配置专属的EntityManagerFactory、TransactionManager,并通过@EnableJpaRepositories明确绑定对应的Repository包:
主库(Apex)配置类示例
@Configuration @EnableJpaRepositories( basePackages = "com.yourproject.apex.repository", // 仅扫描主库的Repository entityManagerFactoryRef = "apexEntityManagerFactory", transactionManagerRef = "apexTransactionManager" ) public class ApexDataSourceConfig { @Primary // 仅主库添加该注解,标记为默认数据源 @Bean(name = "apexDataSource") @ConfigurationProperties(prefix = "spring.datasource.apex") public DataSource dataSource() { return DataSourceBuilder.create().build(); } @Primary @Bean(name = "apexEntityManagerFactory") public LocalContainerEntityManagerFactoryBean apexEntityManagerFactory( EntityManagerFactoryBuilder builder, @Qualifier("apexDataSource") DataSource dataSource) { return builder .dataSource(dataSource) .packages("com.yourproject.apex.entity") // 主库实体类包 .persistenceUnit("apexPU") // 唯一标识,避免与其他库冲突 .build(); } @Primary @Bean(name = "apexTransactionManager") public PlatformTransactionManager apexTransactionManager( @Qualifier("apexEntityManagerFactory") EntityManagerFactory entityManagerFactory) { return new JpaTransactionManager(entityManagerFactory); } }
非主库(比如LOL)配置类示例
@Configuration @EnableJpaRepositories( basePackages = "com.yourproject.lol.repository", // 仅扫描当前库的Repository entityManagerFactoryRef = "lolEntityManagerFactory", transactionManagerRef = "lolTransactionManager" ) public class LolDataSourceConfig { // 不要加@Primary! @Bean(name = "lolDataSource") @ConfigurationProperties(prefix = "spring.datasource.lol") public DataSource dataSource() { return DataSourceBuilder.create().build(); } @Bean(name = "lolEntityManagerFactory") public LocalContainerEntityManagerFactoryBean lolEntityManagerFactory( EntityManagerFactoryBuilder builder, @Qualifier("lolDataSource") DataSource dataSource) { return builder .dataSource(dataSource) .packages("com.yourproject.lol.entity") // 当前库实体类包 .persistenceUnit("lolPU") // 唯一标识 .build(); } @Bean(name = "lolTransactionManager") public PlatformTransactionManager lolTransactionManager( @Qualifier("lolEntityManagerFactory") EntityManagerFactory entityManagerFactory) { return new JpaTransactionManager(entityManagerFactory); } }
2. 严格隔离Repository与实体类的包路径
- 必须将不同库的Repository放在独立包下(比如
apex.repository和lol.repository),避免被其他库的@EnableJpaRepositories扫描到。 - 实体类同理,分库存放(
apex.entity、lol.entity),确保EntityManagerFactory只加载对应库的实体。
3. 校验配置文件的数据源前缀
确保配置文件中两个数据源的前缀与配置类的@ConfigurationProperties完全匹配:
# 主库Apex spring.datasource.apex.url=jdbc:mysql://localhost:3306/apex?useSSL=false&serverTimezone=UTC spring.datasource.apex.username=root spring.datasource.apex.password=xxx spring.datasource.apex.driver-class-name=com.mysql.cj.jdbc.Driver # 非主库LOL spring.datasource.lol.url=jdbc:mysql://localhost:3306/lol?useSSL=false&serverTimezone=UTC spring.datasource.lol.username=root spring.datasource.lol.password=xxx spring.datasource.lol.driver-class-name=com.mysql.cj.jdbc.Driver
4. 绑定事务管理器(若用@Transactional)
如果Controller方法添加了@Transactional,必须指定对应库的事务管理器,否则会默认用主库的:
@RestController @RequestMapping("/lol/users") public class LolUserController { @Autowired private LolUserRepository lolUserRepo; @Transactional("lolTransactionManager") // 指定非主库的事务管理器 @GetMapping("/{id}") public User getLolUser(@PathVariable Long id) { return lolUserRepo.findById(id).orElseThrow(() -> new RuntimeException("用户不存在")); } }
关键错误原因总结
你遇到的Table 'apex.user' doesn't exist,本质是非主库的Repository被主库的@EnableJpaRepositories扫描并绑定到了主库数据源,或者非主库的配置类缺少必要的绑定配置,导致Spring fallback到主库的默认配置。
内容的提问来源于stack exchange,提问作者Ajiva
相关产品推荐
相关产品推荐

