In Java
with Spring Boot
framework there is an @Bean
named DataSource
that is used to make connections to a database, and is used by another @Bean
called JdbcTemplate
that serves to perform actions on the database. But, there is a problem, this @Bean
DataSource
, which serves to make the connection to the database, requires the properties for the connection to be preconfigured (url, username and password). The @Bean
DataSource
needs to start with an "empty" or "default" value at project startup, and at runtime it changes this value. I want a certain Endpoint to execute the action of changing the value of @Bean
, to be more exact. And with the change of the value of the @Bean
DataSource
the JdbcTemplate
, consequently, will be able to perform actions in several database.
Some details:
@Bean
DataSource
at runtime, maybe just override the @Bean
values that the Spring Boot itself already creates automatically. @Bean
DataSource
start with an "empty" value by making a method with the @Bean
annotation and that returns a DataSource
object that is literally this code: DataSourceBuilder.build().create();
. DataSource
@Bean
code:
@Bean
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}
Main class:
@SpringBootApplication(scanBasePackages = "br.com.b2code")
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class RunAdm extends SpringBootServletInitializer implements
CommandLineRunner {
public static final String URL_FRONTEND = "*";
/**
* Método main do módulo de Gestão.
*
* @param args argumentos de inicialização
* @throws Exception uma exception genérica
*/
public static void main(String[] args) throws Exception {
SpringApplication.run(RunAdm.class, args);
}
@Override
protected SpringApplicationBuilder
configure(SpringApplicationBuilder application) {
return application.sources(RunAdm.class);
}
@Override
public void run(String... args) throws Exception {
}
}
A class to exemplify how I use JdbcTemplate
:
@Repository
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class ClienteQueryRepositoryImpl implements ClienteQueryRepository {
private final @NonNull
JdbcTemplate jdbc;
@Override
public List<Cliente> findAll() {
return jdbc.query(ClienteQuerySQL.SELECT_ALL_CLIENTE_SQL, new ClienteRowMapper());
}
}
I think as a general approach you might consider a Proxy Design Pattern for the actual DataSource Implementation.
Let's suppose the DataSource
is an interface that has getConnection
method by user and password (other methods are not really important because this answer is theoretical):
interface DataSource {
Connection getConnection(String user, String password);
}
Now, in order to maintain many databases you might want to provide an implementation of the datasource which will act as a proxy for other datasources that will be created on the fly (upon the endpoint call as you say).
Here is an example:
public class MultiDBDatasource implements DataSource {
private DataSourcesRegistry registry;
public Connection getConnection(String user, String password) {
UserAndPassword userAndPassword = new UserAndPassword(user, password);
registry.get(userAndPassword);
}
}
@Component
class DataSourcesRegistry {
private Map<UserAndPassword, DataSource> map = ...
public DataSource get(UserAndPassword a) {
map.get(a);
}
public void addDataSource(UserAndPassword cred, DataSource ds) {
// add to Map
map.put(...)
}
}
@Controller
class InvocationEndPoint {
// injected by spring
private DataSourcesRegistry registry;
@PostMapping ...
public void addNewDB(params) {
DataSource ds = createDS(params); // not spring based
UserAndPassword cred = createCred(params);
registry.addDataSource(cred, ds);
}
}
A couple of notes:
You should "override" the bean of DataSource offered by spring - this can be done by defining your own bean with the same name in your own configuration that will take precedence over spring's definition.
Spring won't create Dynamic Data Source, they'll be created from the "invocation point" (controller in this case for brevity, in real life probably some service). in any case only Registry will be managed by spring, not the data sources.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.