简体   繁体   English

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

[英]NoUniqueBeanDefinitionException when multiple datasources in Spring Boot and Mybatis project

When configuring multiple datasources in Spring Boot and Mybatis project, following Exception occurs:在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.invokeW org.springframework.beans.factory.NoUniqueBeanDefinitionException:没有可用的“org.springframework.transaction.PlatformTransactionManager”类型的合格 bean:预期的单个匹配 bean,但在 org.springframework.beans.factory.support.DefaultListableBeanFactory 处找到了 2:primaryTx,secondTx。 resolveNamedBean(DefaultListableBeanFactory.java:1041) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE] 在 org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:345) ~ [spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE] 在 org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:340) ~[spring-beans-4.3.13. RELEASE.jar:4.3.13.RELEASE] 在 org.springframework.transaction.interceptor.TransactionAspectSupport.determineTransactionManager(TransactionAspectSupport.java:384) ~[spring-tx-4.3.13.RELEASE.jar:4.3.13.RELEASE] 在org.springframework.transaction.interceptor.TransactionAspectSupport.invokeW ithinTransaction(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] ithinTransaction(TransactionAspectSupport.java:272) ~[spring-tx-4.3.13.RELEASE.jar:4.3.13.RELEASE] 在 org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) ~[spring -tx-4.3.13.RELEASE.jar:4.3.13.RELEASE] 在 org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.3.13.RELEASE.jar: 4.3.13.RELEASE] 在 org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213) ~[spring-aop-4.3.13.RELEASE.jar:4.3.13.RELEASE] 在 com.sun。 proxy.$Proxy86.findByDomain(Unknown Source) ~[na:na]

start of project项目开始

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

datasource configuration数据源配置

@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();
    }
}

Transaction交易

@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);
    }
}

The problem here is that you are defining two beans as datasource and two beans as TransactionManager but you didn't specify which one of them is the primary one, this won't work because Spring needs one datasource bean and one TransactionManager bean to be defined as primary if more than one are defined .这里的问题是您将两个beans定义为datasource ,将两个beans定义为TransactionManager但您没有指定其中哪一个是primary这将不起作用,因为Spring需要定义一个datasource bean 和一个TransactionManager bean如果定义了多个作为主要的

What you should do here is to define, one of your datasources beans and one of your TransactionManager beans as Primary , so that Spring can run correctly, to do so you will need to use @Primary annotation .您应该在这里做的是将您的数据源beans之一和 TransactionManager beans之一定义为Primary ,以便 Spring 可以正确运行,为此您需要使用@Primary annotation

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

Please refer to the Spring's Configure two datasources section from the Documentation.请参阅文档中Spring 的配置两个数据源部分

First,thanks √ answer,it solved my problem perfectly.首先感谢√的回答,完美解决了我的问题。

And I can offer another way of thinking.Unnecessary @Primary to someone,you can define like @Transactional("primaryTx") in your service.而且我可以提供另一种思维方式。对某人@Primary ,您可以在您的服务中定义@Transactional("primaryTx")

like this:像这样:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM