Reputation: 305
When configuring multiple datasources in Spring Boot and Mybatis project, following Exception occurs:
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]
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);
}
}
Upvotes: 1
Views: 3058
Reputation: 1
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.
like this:
@Override
@Transactional("primaryTx")
public Test update() {
Test entity = new Test();
entity.setId(1L);
entity.setPhone("19900000050");
return testRepository.save(entity);
}
Upvotes: 0
Reputation: 32145
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.
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.
@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.
Upvotes: 2