Для поддержки нескольких и разных источников данных в одном большом контексте приложения Spring, я реализовал генерацию соответствующего компонента DataSource
в каждом модуле вручную.
Но до сих пор у меня проблема в том, что DataSource бин генерируется дважды, и далее миграция Flyway вызывается дважды. Я добавил соответствующий комментарий в коде ниже, чтобы обозначить места, которые вызываются дважды.
Я думаю, что это как-то связано с ComponentScan и / или Конфигурацией. Я также пытался пометить Бины в конфигурации DataSource как @Primary
, но безрезультатно.
ModuleApplication
@SpringBootApplication
public class Module1Application {
public static void main(String[] args) {
new SpringApplicationBuilder(Module1Application.class)
.run(args);
}
}
Module1 Config
@SpringBootConfiguration
@ComponentScan(basePackages = {"com.example.module1"})
@PropertySource("module1.properties")
@EnableTransactionManagement
@EnableConfigurationProperties({Module1DataSourceConfig.class})
@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class, HibernateJpaAutoConfiguration.class})
public class Module1Config {
// some other beans
}
Module1DataSourceConfig
@ConfigurationProperties(prefix = "module1.datasource")
@EnableTransactionManagement
@EnableJpaRepositories(
entityManagerFactoryRef = "module1EntityManagerFactory",
transactionManagerRef = "module1TransactionManager",
basePackages = "com.example.module1.repository")
@RequiredArgsConstructor
public class Module1DataSourceConfig extends HikariConfig {
@Bean(name = "module1DataSource")
public DataSource dataSource() {
// Gets invoked twice
return new HikariDataSource(this);
}
@Bean(name = "modul1EntityManagerFactory")
public LocalContainerEntityManagerFactoryBean modul1EntityManagerFactory(@Qualifier("module1DataSource") final DataSource dataSource) {
final LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setJpaVendorAdapter(this.jpaHibernateVendorAdapter());
entityManagerFactoryBean.setDataSource(dataSource);
entityManagerFactoryBean.setPersistenceProviderClass(HibernatePersistenceProvider.class);
entityManagerFactoryBean.setPersistenceUnitName("module1");
entityManagerFactoryBean.setPackagesToScan("com.example.module1.entities");
entityManagerFactoryBean.setJpaProperties(this.hibernateProperties());
entityManagerFactoryBean.afterPropertiesSet();
return entityManagerFactoryBean;
}
@Bean(name = "module1TransactionManager")
public PlatformTransactionManager module1TransactionManager(
@Qualifier("module1EntityManagerFactory") final EntityManagerFactory emf) {
return new JpaTransactionManager(emf);
}
private HibernateJpaVendorAdapter jpaHibernateVendorAdapter() {
// return vendor
}
private Properties hibernateProperties() {
// return props.
}
@Bean(name="module1Flyway", initMethod = "migrate")
@ConditionalOnProperty(prefix = "moudle1.flyway", name = "enabled", matchIfMissing = true)
public Flyway flyway(@Qualifier("module1DataSource") final DataSource dataSource, final Modul1flywayConfig module1FlywayConfig) {
// Gets invoked twice
return Flyway
.configure()
.locations(module1FlywayConfig.getLocations())
.dataSource(dataSource)
.load();
}
@Bean
FlywayMigrationInitializer flywayInitializerModul1(@Qualifier("module1Flyway") Flyway flyway) {
// Gets invoked twice
return new FlywayMigrationInitializer(flyway, null);
}
}
Module1FlywayConfig
@Configuration
@ConfigurationProperties(prefix = "module1.flyway")
@Data
public class Module1FlywayConfig {
private boolean placeholderReplacement;
private boolean enabled;
private String[] locations;
}