@Qualifier在Spring Boot中不使用多个DataSource bean

时间:2016-09-29 11:51:02

标签: mysql spring-boot spring-data-jpa multiple-databases

我正在尝试使用四个JPA实体管理器在Spring启动应用程序中设置四个MySQL数据源。我是春季和春季靴子的新手。我用谷歌搜索这个以获得线索,但结果非常令人困惑,有大量的配置方法(但不是处理多数据源),我不知道该怎么做。最后,我正在尝试为每个MySQL数据源设置四个独立的实体管理器,并在事务中单独使用它们。

application.properties

# Database Properties
db.driver: com.mysql.jdbc.Driver
db.urlHotelPos: jdbc:mysql://localhost:3306/hotelwebpos
db.urlHotelFinance: jdbc:mysql://localhost:3306/hotelfinance
db.urlHotelInventory: jdbc:mysql://localhost:3306/hotelinventory
db.urlReservation: jdbc:mysql://localhost:3306/reservation
db.username: user
db.password: passwd

# Hibernate Properties
hibernate.dialect: org.hibernate.dialect.MySQL5Dialect
hibernate.show_sql: true
hibernate.hbm2ddl.auto: update
entitymanager.packagesToScan: com.test.poswebservice.model.*

DBconfigs.java

@Configuration
@EnableTransactionManagement
public class DBconfigs {

    @Bean
    public DataSource dataSourceHotelPos() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(env.getProperty("db.driver"));
        dataSource.setUrl(env.getProperty("db.urlHotelPos"));
        dataSource.setUsername(env.getProperty("db.username"));
        dataSource.setPassword(env.getProperty("db.password"));
        return dataSource;
    }

    @Bean
    public DataSource dataSourceHotelFinance() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(env.getProperty("db.driver"));
        dataSource.setUrl(env.getProperty("db.urlHotelFinance"));
        dataSource.setUsername(env.getProperty("db.username"));
        dataSource.setPassword(env.getProperty("db.password"));
        return dataSource;
    }

    @Bean
    public DataSource dataSourceHotelInventory() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(env.getProperty("db.driver"));
        dataSource.setUrl(env.getProperty("db.urlHotelInventory"));
        dataSource.setUsername(env.getProperty("db.username"));
        dataSource.setPassword(env.getProperty("db.password"));
        return dataSource;
    }

    @Bean
    public DataSource dataSourceReservation() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(env.getProperty("db.driver"));
        dataSource.setUrl(env.getProperty("db.urlReservation"));
        dataSource.setUsername(env.getProperty("db.username"));
        dataSource.setPassword(env.getProperty("db.password"));
        return dataSource;
    }

    @Bean
    @Qualifier("dataSourceHotelPos")
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryHotelPos() {
        LocalContainerEntityManagerFactoryBean entityManagerFactory = new LocalContainerEntityManagerFactoryBean();

        entityManagerFactory.setDataSource(dataSourceHotelPos());

        entityManagerFactory.setPackagesToScan(env.getProperty("entitymanager.packagesToScan"));

        HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        entityManagerFactory.setJpaVendorAdapter(vendorAdapter);

        Properties additionalProperties = new Properties();
        additionalProperties.put("hibernate.dialect", env.getProperty("hibernate.dialect"));
        additionalProperties.put("hibernate.show_sql", env.getProperty("hibernate.show_sql"));
        additionalProperties.put("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
        entityManagerFactory.setJpaProperties(additionalProperties);

        return entityManagerFactory;
    }

    @Bean
    @Qualifier("dataSourceHotelFinance")
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryHotelFinance() {
        LocalContainerEntityManagerFactoryBean entityManagerFactory = new LocalContainerEntityManagerFactoryBean();

        entityManagerFactory.setDataSource(dataSourceHotelFinance());

        entityManagerFactory.setPackagesToScan(env.getProperty("entitymanager.packagesToScan"));

        HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        entityManagerFactory.setJpaVendorAdapter(vendorAdapter);

        Properties additionalProperties = new Properties();
        additionalProperties.put("hibernate.dialect", env.getProperty("hibernate.dialect"));
        additionalProperties.put("hibernate.show_sql", env.getProperty("hibernate.show_sql"));
        additionalProperties.put("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
        entityManagerFactory.setJpaProperties(additionalProperties);

        return entityManagerFactory;
    }

    @Bean
    @Qualifier("dataSourceHotelInventory")
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryHotelInventory(){
        LocalContainerEntityManagerFactoryBean entityManagerFactory = new LocalContainerEntityManagerFactoryBean();

        entityManagerFactory.setDataSource(dataSourceHotelInventory());

        entityManagerFactory.setPackagesToScan(env.getProperty("entitymanager.packagesToScan"));

        HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        entityManagerFactory.setJpaVendorAdapter(vendorAdapter);

        Properties additionalProperties = new Properties();
        additionalProperties.put("hibernate.dialect", env.getProperty("hibernate.dialect"));
        additionalProperties.put("hibernate.show_sql", env.getProperty("hibernate.show_sql"));
        additionalProperties.put("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
        entityManagerFactory.setJpaProperties(additionalProperties);

        return entityManagerFactory;
    }

    @Bean
    @Qualifier("dataSourceReservation")
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryReservation() {
        LocalContainerEntityManagerFactoryBean entityManagerFactory = new LocalContainerEntityManagerFactoryBean();

        entityManagerFactory.setDataSource(dataSourceReservation());

        entityManagerFactory.setPackagesToScan(env.getProperty("entitymanager.packagesToScan"));

        HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        entityManagerFactory.setJpaVendorAdapter(vendorAdapter);

        Properties additionalProperties = new Properties();
        additionalProperties.put("hibernate.dialect", env.getProperty("hibernate.dialect"));
        additionalProperties.put("hibernate.show_sql", env.getProperty("hibernate.show_sql"));
        additionalProperties.put("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
        entityManagerFactory.setJpaProperties(additionalProperties);

        return entityManagerFactory;
    }

    @Bean
    @Qualifier("entityManagerFactoryHotelPos")
    public JpaTransactionManager transactionManagerHotelPos() {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(entityManagerFactoryHotelPos().getObject());
        return transactionManager;
    }

    @Bean
    @Qualifier("entityManagerFactoryHotelFinance")
    public JpaTransactionManager transactionManagerHotelFinance() {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(entityManagerFactoryHotelFinance().getObject());
        return transactionManager;
    }

    @Bean
    @Qualifier("entityManagerFactoryHotelInventory")
    public JpaTransactionManager transactionManagerHotelInventory() {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(entityManagerFactoryHotelInventory().getObject());
        return transactionManager;
    }

    @Bean
    @Qualifier("entityManagerFactoryReservation")
    public JpaTransactionManager transactionManagerReservation() {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(entityManagerFactoryReservation().getObject());
        return transactionManager;
    }

    @Bean
    public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
        return new PersistenceExceptionTranslationPostProcessor();
    }

    @Autowired
    private Environment env;
}

输出>>

***************************
APPLICATION FAILED TO START
***************************

Description:

Method entityManagerFactoryHotelPos in com.test.poswebservice.configs.DBconfigs required a single bean, but 4 were found:
    - dataSourceHotelPos: defined by method 'dataSourceHotelPos' in class path resource [com/test/poswebservice/configs/DBconfigs.class]
    - dataSourceHotelFinance: defined by method 'dataSourceHotelFinance' in class path resource [com/test/poswebservice/configs/DBconfigs.class]
    - dataSourceHotelInventory: defined by method 'dataSourceHotelInventory' in class path resource [com/test/poswebservice/configs/DBconfigs.class]
    - dataSourceReservation: defined by method 'dataSourceReservation' in class path resource [com/test/poswebservice/configs/DBconfigs.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

@Qualifier注释应该避免这个问题,但在这里它不能以某种方式工作。我在这里做错了什么?请有人帮助我,这几乎杀了我:-(任何帮助都将受到高度赞赏。

感谢。

3 个答案:

答案 0 :(得分:0)

在我的设置中,它以这样的方式工作:

  1. 从EMF bean中删除@Qualifier
  2. 使用正确的@DependsOn({"dataSource"})
  3. 添加每个EMF Bean:DataSource
  4. 确实制作了DataSource s @Primary
  5. 中的一个

答案 1 :(得分:0)

应该这样编写代码:

@Bean(name = "dataSourceHotelPos")
public DataSource dataSourceHotelPos() {
...

答案 2 :(得分:0)

我不知道它是否可以解决您的问题(我的声誉不允许我对此发表评论),但是,您不应在bean定义内调用EMF方法,因为spring已经为此启动了bean 。调用该方法将创建另一个具有完全相同设置的bean。

相反,您可以尝试如下操作:

@Bean
@Qualifier("entityManagerFactoryHotelPos")
public JpaTransactionManager transactionManagerHotelPos(@Qualifier("dataSourceHotelPos") LocalContainerEntityManagerFactoryBean entityManagerFactoryHotelPos) {
    JpaTransactionManager transactionManager = new JpaTransactionManager();
    transactionManager.setEntityManagerFactory(entityManagerFactoryHotelPos.getObject());
    return transactionManager;
}

由于spring将尝试启动此bean,因此它具有autowire构造函数参数。 希望对您有所帮助。