使用MyBatis的Spring:期望的单个匹配bean但找到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(); } } 

两个映射器,以及一个自动assembly映射器的服务:

 @Service public class DbService { @Autowired private DbMapperA dbMapperA; @Autowired private DbMapperB dbMapperB; public List getDabaseARecords(){ return dbMapperA.getDatabaseARecords(); } public List 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注释消除自动assembly的歧义,但我不知道在哪里添加它。

你能看出我哪里出错吗?

如果要同时使用两个数据源且它们不是主数据源和辅助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 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 getDabaseARecords(){ return dbMapperA.getDatabaseARecords(); } public List getDabaseBRecords(){ return dbMapperB.getDatabaseBRecords(); } } 

我有同样的问题,无法启动我的Spring Boot应用程序,并通过重命名有问题的类和处理它的所有层,奇怪的是应用程序启动成功。

我有类UOMServiceUOMServiceImpl UOMRepositoryUOMRepositoryImpl 。 我将它们重命名为UomServiceUomServiceImplUomRepositoryUomRepositoryImpl ,这解决了这个问题!