【Spring】複数データベースを参照すると、beanが複数存在しているというエラーが出ます
解決済
回答 1
投稿
- 評価
- クリップ 1
- VIEW 5,056
前提・実現したいこと
Springで一つのデータベースから情報を持ってくることは出来ているのですが、複数のデータベースを指定するとエラーが出ます。
データベースの参照は、(データベース名)Config.javaというファイル内に記述しており、@Beanもこの中で記述しています。
@Configurationというアノテーションを付与しており、これを外せば付いている方のデータベースを参照して、外した方のファイルは読み込まれないようになります。
また、エラーは実際に処理させたいタイミングではなく、アプリケーションを起動する時に発生しています。
同じアプリケーション内で複数データベースを同時に参照したいため、@Configurationをどちらにも付与している状態で処理したいです。
@ConfigurationProperties(prefix = "config.hoge")というアノテーションを付与したり、
createDtaSourceで作成されるものの名称を変えてみるといった対処をしてみたのですが、解決できませんでした。
対処法をご存知の方いらっしゃいましたら、ご教示よろしくお願いいたします。
発生している問題・エラーメッセージ
Parameter 0 of constructor in com.example.sample.repository.hoge.HogeDaoImpl required a single bean, but 2 were found:
- hogeConfig: defined in file [/Users/****/sample/target/classes/com/example/sample/config/HogeConfig.class]
- fugaConfig: defined in file [/Users/****/sample/target/classes/com/example/sample/config/FugaConfig.class]
Action:
Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed
HogeConfig.class
package com.example.sample.config;
import javax.sql.DataSource;
import org.seasar.doma.jdbc.Config;
import org.seasar.doma.jdbc.JdbcLogger;
import org.seasar.doma.jdbc.SimpleDataSource;
import org.seasar.doma.jdbc.dialect.Dialect;
import org.seasar.doma.jdbc.dialect.MysqlDialect;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration
@EnableTransactionManagement
public class HogeConfig implements Config {
private DataSource dataSource = createDataSource();
private Dialect dialect = new MysqlDialect();
@Override
public DataSource getDataSource() {
// TODO Auto-generated method stub
return dataSource;
}
@Override
public Dialect getDialect() {
// TODO Auto-generated method stub
return dialect;
}
@Bean
public PlatformTransactionManager transactionManager() {
return new DataSourceTransactionManager(dataSource);
}
protected static DataSource createDataSource() {
SimpleDataSource dataSource = new SimpleDataSource();
dataSource.setUrl("jdbc:postgresql://localhost:1234/hoge");
dataSource.setUser("******");
dataSource.setPassword("******");
return new TransactionAwareDataSourceProxy(dataSource);
}
}
FugaConfig.class
package com.example.sample.config;
import javax.sql.DataSource;
import org.seasar.doma.jdbc.Config;
import org.seasar.doma.jdbc.JdbcLogger;
import org.seasar.doma.jdbc.SimpleDataSource;
import org.seasar.doma.jdbc.dialect.Dialect;
import org.seasar.doma.jdbc.dialect.MysqlDialect;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration
@EnableTransactionManagement
public class FugaConfig implements Config {
private DataSource dataSource = createDataSource();
private Dialect dialect = new MysqlDialect();
@Override
public DataSource getDataSource() {
// TODO Auto-generated method stub
return dataSource;
}
@Override
public Dialect getDialect() {
// TODO Auto-generated method stub
return dialect;
}
@Bean
public PlatformTransactionManager transactionManager() {
return new DataSourceTransactionManager(dataSource);
}
protected static DataSource createDataSource() {
SimpleDataSource dataSource = new SimpleDataSource();
dataSource.setUrl("jdbc:postgresql://localhost:1234/fuga");
dataSource.setUser("******");
dataSource.setPassword("******");
return new TransactionAwareDataSourceProxy(dataSource);
}
}
補足情報(FW/ツールのバージョンなど)
Spring Tool Suit 4
Postgres
Mac OS
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
+1
複数のデータソースが DataSource の名前で重複してしまっているので、@Beanで名前を明示的につけてあげると解決するかと思います。
なお、よくひっかかる問題でもあるようです。
以下Qiitaを参考にしてください。
Spring Boot 1.5で複数データベースを扱うウェブアプリケーションのサンプル
SpringBootで2つのデータソースを使う(MyBatis)
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.37%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
2018/12/07 21:32
参考にしつつ下記のように変更してみたのですが、HogeDao.javaからHogeConfigを呼び出すと正常にhogeデータベースが呼ばれるのですが、FugaDao.javaからFugaConfigを呼び出そうとしても、@PrimaryのせいかHogeConfigが呼ばれてしまい、「FugaテーブルはHogeデータベースに存在しません」と怒られてしまいます。
おそらく@Primaryの影響でDAOで記述しているアノテーションが効いておらず、常に@PrimaryがついたConfigを参照してしまっていると思われます。
なぜDAOに記述してあるアノテーションが効いていないのか分かりますでしょうか。。
ご教示いただけると幸いです。
==============================
【HogeDao.java】
@ConfigAutowireable
@Dao(config = HogeConfig.class)
@Transactional(transactionManager = "txManager1")
public interface HogeDao {
:
}
==============================
【FugaDao.java】
@ConfigAutowireable
@Dao(config = FugaConfig.class)
@Transactional(transactionManager = "txManager2")
public interface FugaDao {
:
}
==============================
【HogeConfig.class】
@Configuration
@EnableTransactionManagement
@Primary
public class HogeConfig implements Config {
@Bean
@ConfigurationProperties(prefix = "spring.datasource")
public DataSourceProperties datasource2Properties() {
return new DataSourceProperties();
}
@Bean(name = {"datasource2"})
public DataSource datasource2(
@Qualifier("datasource2Properties") DataSourceProperties properties) {
return properties.initializeDataSourceBuilder().build();
}
@Bean(name = {"txManager2"})
public PlatformTransactionManager txManager2(DataSource dataSource2) {
return new DataSourceTransactionManager(dataSource2);
}
@Bean(name = {"sqlSessionFactory2"})
public SqlSessionFactory sqlSessionFactory(@Qualifier("datasource2") DataSource datasource2)
throws Exception {
SqlSessionFactoryBean sqlSessionFactory = new SqlSessionFactoryBean();
sqlSessionFactory.setDataSource(datasource2);
return (SqlSessionFactory) sqlSessionFactory.getObject();
}
private DataSource dataSource = createDataSource();
private Dialect dialect = new MysqlDialect();
@Override
public DataSource getDataSource() {
// TODO Auto-generated method stub
return dataSource;
}
@Override
public Dialect getDialect() {
// TODO Auto-generated method stub
return dialect;
}
@Bean
public PlatformTransactionManager transactionManager() {
return new DataSourceTransactionManager(dataSource);
}
protected static DataSource createDataSource() {
SimpleDataSource dataSource = new SimpleDataSource();
dataSource.setUrl("jdbc:postgresql://localhost:1234/hoge");
dataSource.setUser("******");
dataSource.setPassword("******");
return new TransactionAwareDataSourceProxy(dataSource);
}
}
==============================
【FugaConfig.class】
@Configuration
@EnableTransactionManagement
@Primary
public class FugaConfig implements Config {
@Bean
@ConfigurationProperties(prefix = "spring.datasource")
public DataSourceProperties datasource2Properties() {
return new DataSourceProperties();
}
@Bean(name = {"datasource2"})
public DataSource datasource2(
@Qualifier("datasource2Properties") DataSourceProperties properties) {
return properties.initializeDataSourceBuilder().build();
}
@Bean(name = {"txManager2"})
public PlatformTransactionManager txManager2(DataSource dataSource2) {
return new DataSourceTransactionManager(dataSource2);
}
@Bean(name = {"sqlSessionFactory2"})
public SqlSessionFactory sqlSessionFactory(@Qualifier("datasource2") DataSource datasource2)
throws Exception {
SqlSessionFactoryBean sqlSessionFactory = new SqlSessionFactoryBean();
sqlSessionFactory.setDataSource(datasource2);
return (SqlSessionFactory) sqlSessionFactory.getObject();
}
private DataSource dataSource = createDataSource();
private Dialect dialect = new MysqlDialect();
@Override
public DataSource getDataSource() {
// TODO Auto-generated method stub
return dataSource;
}
@Override
public Dialect getDialect() {
// TODO Auto-generated method stub
return dialect;
}
@Bean
public PlatformTransactionManager transactionManager() {
return new DataSourceTransactionManager(dataSource);
}
protected static DataSource createDataSource() {
SimpleDataSource dataSource = new SimpleDataSource();
dataSource.setUrl("jdbc:postgresql://localhost:1234/fuga");
dataSource.setUser("******");
dataSource.setPassword("******");
return new TransactionAwareDataSourceProxy(dataSource);
}
}
2018/12/10 09:47
2018/12/10 20:59
よろしくお願い致します。
2018/12/11 13:48
こちらのサイトを参考に、Daoで@ConfigAutoWiredとしていた部分を、@AnnotateWithで書き換えることで解決することができました!
【HogeDao.java】
@AnnotateWith(annotations = {
@Annotation(target = AnnotationTarget.CLASS, type = Repository.class),
@Annotation(target = AnnotationTarget.CLASS, type = Component.class),
@Annotation(target = AnnotationTarget.CONSTRUCTOR, type = Autowired.class),
@Annotation(target = AnnotationTarget.CONSTRUCTOR_PARAMETER, type = Qualifier.class, elements = "\"HogeConfig\"")
})
@Dao
public interface HogeDao {
:
}
【DomaConfig.class】
@Configuration
@EnableTransactionManagement
@Primary
public class HogeConfig implements Config {
private DataSource dataSource = createDataSource();
private Dialect dialect = new MysqlDialect();
@Override
public DataSource getDataSource() {
return dataSource;
}
@Override
public Dialect getDialect() {
return dialect;
}
@Bean
public PlatformTransactionManager transactionManager() {
return new DataSourceTransactionManager(dataSource);
}
protected static DataSource createDataSource() {
SimpleDataSource dataSource = new SimpleDataSource();
dataSource.setUrl("jdbc:postgresql://localhost:1234/hoge");
dataSource.setUser("******");
dataSource.setPassword("******");
return new TransactionAwareDataSourceProxy(dataSource);
}
}
【HogeConfig.class】
@Configuration
@EnableTransactionManagement
@Component("HogeConfig")
public class HogeConfig implements Config {
private DataSource dataSource = createDataSource();
private Dialect dialect = new MysqlDialect();
@Override
public DataSource getDataSource() {
return dataSource;
}
@Override
public Dialect getDialect() {
return dialect;
}
@Bean
public PlatformTransactionManager transactionManager() {
return new DataSourceTransactionManager(dataSource);
}
protected static DataSource createDataSource() {
SimpleDataSource dataSource = new SimpleDataSource();
dataSource.setUrl("jdbc:postgresql://localhost:1234/hoge");
dataSource.setUser("******");
dataSource.setPassword("******");
return new TransactionAwareDataSourceProxy(dataSource);
}
}