2016-03-23 25 views
4

私はMyBatisでSpringを使用していました。私は別のデータベースを追加しようとすると問題に遭遇しました(reproducible example on Github参照)。SpringとMyBatis:期待される単一の一致するBeanが見つかりましたが、2が見つかりました。

私はSpringのJava設定(つまりXMLではなく)を使用しています。私が見た例のほとんどは、XMLを使ってこれを達成する方法を示しています。

私はこのような二つのデータ設定クラス(& B)持っている:マッパー、およびマッパーをautowiresサービス

@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の注釈を使ってオートワイヤリングを曖昧さを取り除きましたが、どこに追加するかはわかりませんでした。

どこが間違っているのか分かりますか?

+0

完全なエラーメッセージを投稿できますか?通常springはautowiredフィールドとエラーを引き起こすBeanを指示します。 – ben75

+0

'@Qaulifier(" name_of_bean ")'は、特定のフィールドの '@ Autowired'アノテーションの前後に置くことができます。 – BretC

+0

Thanks @ Ben75私は完全な出力をhttps://gist.github.com/alexwoolford/1f3e799deb3be32a4356 –

答えて

1

を最後に、我々は独自のフォルダ内の各マッパーを置く:

src/main/java/io/woolford/database/mapper/a/DbMapperA.java 
src/main/java/io/woolford/database/mapper/c/DbMapperB.java 

は、我々は2つのDataConfigのクラス、それぞれに1つずつ作成しましたデータベース。 @MapperScan注釈でexpected single matching bean but found 2問題が解決されました。

@Configuration 
@MapperScan(value = {"io.woolford.database.mapper.a"}, sqlSessionFactoryRef="sqlSessionFactoryA") 
public class DataConfigDatabaseA { 

DataConfigクラスの一つで豆に@Primary注釈を追加する必要がありました:助けたすべての人に

@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})を試しましたが、それはさらにエラーが発生しました。

それは便利です、私たちのために働いたソリューションはここに掲載された場合には

2

同時に2つのデータソースを使用する場合は、プライマリとセカンダリではないので、@SpringBootApplicationで注釈を付けたアプリケーションので@EnableAutoConfiguration(excludes = {DataSourceAutoConfiguration.class})を無効にする必要があります。その後、独自のSqlSessionFactoryを作成し、独自のDataSourceをバンドルすることができます。 DataSourceTransactionManagerも使用したい場合は、それも行う必要があります。この場合

は、あなたが DataSourceAutoConfigurationを無効にしていないので、Springフレームワークは @Autowired一つだけ DataSourceにしようとしますが、2つ持って、エラーが発生します。

これまで説明したように、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"); 
    } 
} 
+0

何が役立つ答えですか? '@EnableAutoConfiguration(excludes = DataSourceAutoConfiguration.class)'または '@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)'のいずれかです。 – sjngm

+0

ありがとう!これで1時間を費やしました! –

0

あなたは、問題は、あなたが春のコンテナに2つの同じ種類の豆を持っているということです@Qualifier注釈

を使用することができます。 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(); 
    } 

} 
0

https://github.com/alexwoolford/mybatis-spring-multiple-mysql-reproducible-example私は同じ問題を持っていたし、私の春のブートアプリケーションを起動することができませんでしたし、問題のあるクラスの名前を変更して、そして配らすべての層不思議なことに、アプリケーションが正常に起動しました。

私はクラスUOMService,UOMServiceImplUOMRepositoryおよびUOMRepositoryImplを持っています。私はそれらの名前をUomService,UomServiceImpl,UomRepositoryUomRepositoryImplに変更し、問題を解決しました!

関連する問題