[英]Spring with MyBatis: expected single matching bean but found 2
我一直在使用Spring和MyBatis,它在單個數據庫中運行得非常好。 我在嘗試添加另一個數據庫時遇到了困難(請參閱Github上的可重復示例 )。
我正在使用Spring Java配置(即不是XML)。 我見過的大多數示例都展示了如何使用XML實現這一點。
我有兩個數據配置類(A和B),如下所示:
@Configuration
@MapperScan("io.woolford.database.mapper")
public class DataConfigDatabaseA {
@Bean(name="dataSourceA")
public DataSource dataSourceA() throws SQLException {
SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
dataSource.setDriver(new com.mysql.jdbc.Driver());
dataSource.setUrl("jdbc:mysql://" + dbHostA + "/" + dbDatabaseA);
dataSource.setUsername(dbUserA);
dataSource.setPassword(dbPasswordA);
return dataSource;
}
@Bean
public SqlSessionFactory sqlSessionFactory() throws Exception {
SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
sessionFactory.setDataSource(dataSourceA());
return sessionFactory.getObject();
}
}
兩個映射器,以及一個自動裝配映射器的服務:
@Service
public class DbService {
@Autowired
private DbMapperA dbMapperA;
@Autowired
private DbMapperB dbMapperB;
public List<Record> getDabaseARecords(){
return dbMapperA.getDatabaseARecords();
}
public List<Record> getDabaseBRecords(){
return dbMapperB.getDatabaseBRecords();
}
}
該應用程序將無法啟動:
Error creating bean with name 'dataSourceInitializer':
Invocation of init method failed; nested exception is
org.springframework.beans.factory.NoUniqueBeanDefinitionException:
No qualifying bean of type [javax.sql.DataSource] is defined:
expected single matching bean but found 2: dataSourceB,dataSourceA
我已經讀過可以使用@Qualifier
注釋消除自動裝配的歧義,但我不知道在哪里添加它。
你能看出我出錯的地方嗎?
如果要同時使用兩個數據源並且它們不是主數據源和輔助DataSourceAutoConfiguration
, @EnableAutoConfiguration(excludes = {DataSourceAutoConfiguration.class})
通過@SpringBootApplication
注釋的應用程序上的@EnableAutoConfiguration(excludes = {DataSourceAutoConfiguration.class})
禁用DataSourceAutoConfiguration
。 之后,您可以創建自己的SqlSessionFactory
並捆綁自己的DataSource
。 如果您還想使用DataSourceTransactionManager
,您也應該這樣做。
在這種情況下,您還沒有禁用DataSourceAutoConfiguration
,因此Spring框架將嘗試@Autowired
只有一個DataSource
但是有兩個,發生錯誤。
正如我之前所說,您應該禁用DataSourceAutoConfiguration
並手動配置它。
您可以按如下方式禁用數據源自動配置:
@SpringBootApplication
@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class})
public class YourApplication implements CommandLineRunner {
public static void main (String... args) {
SpringApplication.run(YourApplication.class, args);
}
}
如果你真的想同時使用多個數據庫,我建議你手動注冊正確的bean,例如:
package xyz.cloorc.boot.mybatis;
import org.apache.commons.dbcp.BasicDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.support.SqlSessionDaoSupport;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Repository;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.sql.DataSource;
@Configuration
public class SimpleTest {
private DataSource dsA;
private DataSource dsB;
@Bean(name = "dataSourceA")
public DataSource getDataSourceA() {
return dsA != null ? dsA : (dsA = new BasicDataSource());
}
@Bean(name = "dataSourceB")
public DataSource getDataSourceB() {
return dsB != null ? dsB : (dsB = new BasicDataSource());
}
@Bean(name = "sqlSessionFactoryA")
public SqlSessionFactory getSqlSessionFactoryA() throws Exception {
// set DataSource to dsA
return new SqlSessionFactoryBean().getObject();
}
@Bean(name = "sqlSessionFactoryB")
public SqlSessionFactory getSqlSessionFactoryB() throws Exception {
// set DataSource to dsB
return new SqlSessionFactoryBean().getObject();
}
}
@Repository
public class SimpleDao extends SqlSessionDaoSupport {
@Resource(name = "sqlSessionFactoryA")
SqlSessionFactory factory;
@PostConstruct
public void init() {
setSqlSessionFactory(factory);
}
@Override
public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
super.setSqlSessionFactory(sqlSessionFactory);
}
public <T> T get (Object id) {
return super.getSqlSession().selectOne("sql statement", "sql parameters");
}
}
最后,我們將每個映射器放在自己的文件夾中:
src/main/java/io/woolford/database/mapper/a/DbMapperA.java
src/main/java/io/woolford/database/mapper/c/DbMapperB.java
然后,我們創建了兩個DataConfig
類,每個類對應一個數據庫。 @MapperScan
注釋解析了expected single matching bean but found 2
問題。
@Configuration
@MapperScan(value = {"io.woolford.database.mapper.a"}, sqlSessionFactoryRef="sqlSessionFactoryA")
public class DataConfigDatabaseA {
有必要將@Primary
注釋添加到其中一個DataConfig
類中的bean中:
@Bean(name="dataSourceA")
@Primary
public DataSource dataSourceA() throws SQLException {
...
}
@Bean(name="sqlSessionFactoryA")
@Primary
public SqlSessionFactory sqlSessionFactoryA() throws Exception {
...
}
感謝所有幫助過的人。 毫無疑問,這樣做的方法不止一種。 我按照@eduardlofitskyi和@GeminiKeith的建議嘗試了@Qualifier
和@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class})
,但這又產生了一些錯誤。
萬一它有用,我們的解決方案在這里發布: https : //github.com/alexwoolford/mybatis-spring-multiple-mysql-reproducible-example
您可以使用@Qualifier
注釋
問題是你在Spring容器中有兩個相同的類型bean。 當你嘗試autowire bean時,Spring無法解析哪個bean注入到字段中
@Qualifier
注釋是使用限定符的主要方式。 它可以在注入點與@Autowired
或@Inject
一起應用,以指定要注入的bean。
所以,你的DbService應該是這樣的:
@Service
public class DbService {
@Autowired
@Qualifier("dataSourceA")
private DbMapperA dbMapperA;
@Autowired
@Qualifier("dataSourceB")
private DbMapperB dbMapperB;
public List<Record> getDabaseARecords(){
return dbMapperA.getDatabaseARecords();
}
public List<Record> getDabaseBRecords(){
return dbMapperB.getDatabaseBRecords();
}
}
我有同樣的問題,無法啟動我的Spring Boot應用程序,並通過重命名有問題的類和處理它的所有層,奇怪的是應用程序啟動成功。
我有類UOMService
, UOMServiceImpl
UOMRepository
和UOMRepositoryImpl
。 我將它們重命名為UomService
, UomServiceImpl
, UomRepository
和UomRepositoryImpl
,這解決了這個問題!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.