Spring Boot 和 Mybatis 项目中多个数据源时的 NoUniqueBeanDefinitionException

NoUniqueBeanDefinitionException when multiple datasources in Spring Boot and Mybatis project

在Spring Boot 和Mybatis 项目中配置多个数据源时,出现以下异常:

org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'org.springframework.transaction.PlatformTransactionManager' available: expected single matching bean but found 2: primaryTx,secondTx at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1041) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE] at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:345) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE] at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:340) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE] at org.springframework.transaction.interceptor.TransactionAspectSupport.determineTransactionManager(TransactionAspectSupport.java:384) ~[spring-tx-4.3.13.RELEASE.jar:4.3.13.RELEASE] at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:272) ~[spring-tx-4.3.13.RELEASE.jar:4.3.13.RELEASE] at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) ~[spring-tx-4.3.13.RELEASE.jar:4.3.13.RELEASE] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.3.13.RELEASE.jar:4.3.13.RELEASE] at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213) ~[spring-aop-4.3.13.RELEASE.jar:4.3.13.RELEASE] at com.sun.proxy.$Proxy86.findByDomain(Unknown Source) ~[na:na]

项目开始

@SpringBootApplication( exclude = {
        DataSourceAutoConfiguration.class, 
        DataSourceTransactionManagerAutoConfiguration.class
})
@EnableTransactionManagement
public class BookSystemApplication {
}

数据源配置

@Configuration
public class DataSourceConfig {
    @Bean(name = "primaryDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.primary")
    public DataSource primaryDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "secondDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.second")
    public DataSource secondDataSource() {
        return DataSourceBuilder.create().build();
    }
}

交易

@Configuration
public class TransactionConfig {
    @Autowired
    @Qualifier("primaryDataSource")
    private DataSource primary;

    @Autowired
    @Qualifier("secondDataSource")
    private DataSource second;

    @Bean(name="primaryTx")
    public PlatformTransactionManager primaryTransaction() {
        return new DataSourceTransactionManager(primary);
    }

    @Bean(name="secondTx")
    public PlatformTransactionManager secondTransaction() {
        return new DataSourceTransactionManager(second);
    }
}

这里的问题是您将两个 beans 定义为 datasource 并将两个 bean 定义为 TransactionManager 但您没有指定其中一个是 primary 一,这行不通,因为 Spring 需要一个 datasource bean 和一个 TransactionManager bean 被定义为主要 如果定义了多个.

您在这里应该做的是将您的数据源之一 beans 和您的 TransactionManager beans 之一定义为 Primary,以便 Spring 可以 运行 正确,为此你需要使用 @Primary 注释 .

@Bean(name = "primaryDataSource")
@Primary
@ConfigurationProperties(prefix = "spring.datasource.primary")
public DataSource primaryDataSource() {
    return DataSourceBuilder.create().build();
}

请参阅文档中的 the Spring's Configure two datasources section

首先感谢√的解答,完美解决了我的问题

而且我可以向某人提供 thinking.Unnecessary @Primary 的另一种方式,您可以在您的服务中定义 @Transactional("primaryTx")

像这样:

    @Override
    @Transactional("primaryTx")
    public Test update() {
        Test entity = new Test();
        entity.setId(1L);
        entity.setPhone("19900000050");
        return testRepository.save(entity);
    }