2016-12-07 4 views
1

動的マルチテナントでアプリケーションを作成しています。マスターデータベースには、テナントのDBへの接続を含むテーブルが含まれています。

Everithingは大丈夫です。春のブートアプリケーションが原因で失敗した。しかし:

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

Description: 

Method requestMappingHandlerMapping in org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration$EnableWebMvcConfiguration required a single bean, but 2 were found: 
    - masterEntityManagerFactory: defined by method 'masterEntityManagerFactory' in class path resource [com/dimanex/api/config/MasterDatabaseConfig.class] 
    - tenantEntityManagerFactory: defined by method 'tenantEntityManagerFactory' in class path resource [com/dimanex/api/config/TenantsDatabaseConfig.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 


Process finished with exit code 1 

私はプライマリとして1つのBeanをマークしたが、これは助けませんでした:

@Configuration 
@EnableConfigurationProperties(JpaProperties.class) 
@EnableJpaRepositories(
    entityManagerFactoryRef = MasterDatabaseConfig.MASTER_ENTITY_MANAGER_FACTORY_NAME, 
    transactionManagerRef = MasterDatabaseConfig.MASTER_TRANSACTION_MANAGER_NAME, 
    basePackages = {"com.dimanex.api.repository.master"}) 
@EnableTransactionManagement 
public class MasterDatabaseConfig { 

    public static final String MASTER_ENTITY_MANAGER_FACTORY_NAME = "masterEntityManagerFactory"; 
    public static final String MASTER_TRANSACTION_MANAGER_NAME = "masterTransactionManager"; 

    @Bean(destroyMethod = "close") 
    public DataSource masterDataSource(@Value("${spring.datasource.url}") String url, 
             @Value("${spring.datasource.dataSourceClassName}") String dataSourceClassName, 
             @Value("${spring.datasource.username}") String user, 
             @Value("${spring.datasource.password}") String password) { 

     log.debug("Configuring datasource {} {} {}", dataSourceClassName, url, user); 
     HikariConfig config = new HikariConfig(); 
     config.setDataSourceClassName(dataSourceClassName); 
     config.addDataSourceProperty("url", url); 
     config.addDataSourceProperty("user", user); 
     config.addDataSourceProperty("password", password); 
     return new HikariDataSource(config); 
    } 

    @Bean(name = MASTER_ENTITY_MANAGER_FACTORY_NAME) 
    public LocalContainerEntityManagerFactoryBean masterEntityManagerFactory(DataSource masterDataSource, 
                      JpaProperties jpaProperties) { 
     JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); 
     LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); 
     em.setDataSource(masterDataSource); 
     em.setPackagesToScan(new String[]{MasterBaseObject.class.getPackage().getName()}); 
     em.setJpaVendorAdapter(vendorAdapter); 

     em.setJpaProperties(new Properties(){{ 
      final Properties self = this; 
      jpaProperties.getHibernateProperties(masterDataSource).forEach((k, v) -> self.setProperty(k, v)); 
     }}); 

     em.setPersistenceUnitName("master"); 

     return em; 
    } 

    @Bean(name = MASTER_TRANSACTION_MANAGER_NAME) 
    @Primary 
    public JpaTransactionManager masterTransactionManager(@Qualifier(MASTER_ENTITY_MANAGER_FACTORY_NAME) EntityManagerFactory masterEntityManagerFactory){ 
     JpaTransactionManager transactionManager = new JpaTransactionManager(); 
     transactionManager.setEntityManagerFactory(masterEntityManagerFactory); 
     return transactionManager; 
    } 

} 

テナントのコンフィグ:

@Configuration 
@EnableConfigurationProperties(JpaProperties.class) 
@EnableJpaRepositories(
    entityManagerFactoryRef = TenantsDatabaseConfig.TENANT_ENTITY_MANAGER_FACTORY_NAME, 
    transactionManagerRef = TenantsDatabaseConfig.TENANT_TRANSACTION_MANAGER_NAME, 
    basePackages = {"com.dimanex.api.repository.tenant"}) 
@EnableTransactionManagement 
public class TenantsDatabaseConfig { 

    public static final String TENANT_ENTITY_MANAGER_FACTORY_NAME = "tenantEntityManagerFactory"; 
    public static final String TENANT_TRANSACTION_MANAGER_NAME = "tenantsTransactionManager"; 

    @Bean 
    public JpaVendorAdapter jpaVendorAdapter() { 
     return new HibernateJpaVendorAdapter(); 
    } 

    @Bean 
    public MultiTenantConnectionProvider multiTenantConnectionProvider(@Value("${spring.datasource.dataSourceClassName}") String dataSourceClassName) { 
     return new DimanexMultiTenantConnectionProvider(dataSourceClassName); 
    } 

    @Bean 
    public CurrentTenantIdentifierResolver currentTenantIdentifierResolver() { 
     return new DimanexCurrentTenantResolver(); 
    } 

    @Bean(name = TENANT_ENTITY_MANAGER_FACTORY_NAME) 
    public LocalContainerEntityManagerFactoryBean tenantEntityManagerFactory(@Value("${spring.jpa.properties.hibernate.dialect}") String hibernateDialect, 
                      DataSource masterDataSource, 
                      MultiTenantConnectionProvider connectionProvider, 
                      CurrentTenantIdentifierResolver tenantResolver) { 

     LocalContainerEntityManagerFactoryBean emfBean = new LocalContainerEntityManagerFactoryBean(); 
     emfBean.setPackagesToScan(TenantBaseObject.class.getPackage().getName()); 
     emfBean.setJpaVendorAdapter(jpaVendorAdapter()); 
     emfBean.setDataSource(masterDataSource); 
     Map<String, Object> properties = new HashMap<>(); 
     properties.put(org.hibernate.cfg.Environment.MULTI_TENANT, MultiTenancyStrategy.DATABASE); 
     properties.put(org.hibernate.cfg.Environment.MULTI_TENANT_CONNECTION_PROVIDER, connectionProvider); 
     properties.put(org.hibernate.cfg.Environment.MULTI_TENANT_IDENTIFIER_RESOLVER, tenantResolver); 

     properties.put("hibernate.ejb.naming_strategy", "org.hibernate.cfg.ImprovedNamingStrategy"); 
     properties.put("hibernate.dialect", hibernateDialect); 

     emfBean.setJpaPropertyMap(properties); 

     return emfBean; 
    } 

    @Bean(name = TENANT_TRANSACTION_MANAGER_NAME) 
    public JpaTransactionManager tenantsTransactionManager(@Qualifier(TENANT_ENTITY_MANAGER_FACTORY_NAME) EntityManagerFactory tenantEntityManager) { 
     JpaTransactionManager transactionManager = new JpaTransactionManager(); 
     transactionManager.setEntityManagerFactory(tenantEntityManager); 
     return transactionManager; 
    } 

それはバグのように見えますWebMvcAutoConfiguration $ EnableWebMvcConfigurationで@Primaryを無視する場合

+0

解像度は単純でした。 @PrimaryアノテーションでmasterTransactionManagerをマークしましたが、masterEntityManagerFactory beanはマークしませんでした。 – coreer

答えて

1

解決方法w単純なように。 @PrimaryアノテーションでmasterTransactionManagerをマークしましたが、masterEntityManagerFactory beanはマークしませんでした。

関連する問題