使用MyBatis的Spring:期望的单个匹配bean但找到2

时间:2016-03-23 17:11:49

标签: java spring spring-boot mybatis spring-mybatis

我一直在使用Spring和MyBatis,并且它在单个数据库中运行得非常好。我在尝试添加另一个数据库时遇到了困难(参见reproducible example on 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注释来消除自动装配的歧义,但我不确定在哪里添加它。

你能看到我出错的地方吗?

4 个答案:

答案 0 :(得分:2)

如果您想同时使用两个数据源并且它们不是主要数据源和辅助数据源,则应在$options = mysql_query ("select * from options where pollid='poll'"); echo '<form id="poll">'; while ($row1 = mysql_fetch_array($options)) { $id = $row1['id']; $option = $row1['choice']; $votes = $row1['votes']; echo '<input type="radio" name="optionid" value="'.$id.'" onclick="getVote()" /><span>'.$option.'</span><br />'; } echo '</form>'; 注释的应用程序上按DataSourceAutoConfiguration禁用@EnableAutoConfiguration(excludes = {DataSourceAutoConfiguration.class})。之后,您可以创建自己的@SpringBootApplication并捆绑自己的SqlSessionFactory。如果您还想使用DataSource,也应该这样做。

在这种情况下,您尚未停用DataSourceTransactionManager,因此Spring框架会尝试DataSourceAutoConfiguration只有一个@Autowired但会有两个错误发生。

正如我之前所说,你应该禁用DataSource并手动配置它。

您可以按如下方式禁用数据源自动配置:

DataSourceAutoConfiguration

如果您真的想同时使用多个数据库,我建议您手动注册正确的bean,例如:

@SpringBootApplication
@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class})
public class YourApplication implements CommandLineRunner {
    public static void main (String... args) {
        SpringApplication.run(YourApplication.class, args);
    }
}

答案 1 :(得分:1)

最后,我们将每个映射器放在自己的文件夹中:

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

答案 2 :(得分:0)

您可以使用@Qualifier注释

问题是Spring容器中有两个相同的类型bean。当你尝试autowire bean时,Spring无法解析哪个bean注入到字段

@Qualifier注释是使用限定符的主要方式。它可以在注射点与@Autowired@Inject一起应用,以指定您想要注射的豆。

因此,您的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();
    }

}

答案 3 :(得分:0)

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

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