I have a spring boot project where I have to process files. According to a specific number in the filename the following actions (e.g. persisting some data) will rely on a certain database schema. There are around 100 schemas to fill.
I want to set the Datasource dynamically. As only the username and the password differs but can be generated by using a template and just replace the number. The remaining values stay the same.
As there are around 100 possible target schemas I do not wnt to implement a solution using an AbstractRoutingDatasource like in described in this or this article.
This is what I have so far:
@Configuration
public class CustomDatasourceConfiguration {
@Lazy
@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public DataSource dynamicDataSource() {
DataSourceBuilder<?> dsBuilder = DataSourceBuilder.create();
DatabaseConfiguration configuration = DBContextHolder.getCurrentConfiguration();
dsBuilder.driverClassName(configuration.getDriverClassName());
dsBuilder.url(configuration.getUrl());
dsBuilder.username(configuration.getUsername());
dsBuilder.password(configuration.getPassword());
return dsBuilder.build();
}
@Lazy
@Qualifier("customJdbcTemplate")
@Bean
public JdbcTemplate customJdbcTemplate() {
return new JdbcTemplate(dynamicDataSource());
}
DatabaseConfiguration is only a wrapper object that gets the values from application.properties and generates the access data from the template using the specific number. It defaults to the values set within application.properties spring.datasource.xxx if no specific number has been set.
The current configuration could be set via DBContextHolder. At the beginning of the Process a new DatabaseConfiguration object with the proper number is created and set to the context holder.
public class DBContextHolder {
private static final ThreadLocal<DatabaseConfiguration> contextHolder = new ThreadLocal<>();
public static void setCurrentConfiguration(DatabaseConfiguration configuration) {
contextHolder.set(configuration);
}
public static DatabaseConfiguration getCurrentConfiguration() {
return contextHolder.get();
}
public static void clear() {
contextHolder.remove();
}
Question is if this is sufficient for spring boot and especially all the JPA Stuff (JPARepository interfaces) will use this datasource? Or do I need to do some extra configuration?
Any hint is appreciated.