I have a Spring Boot project with multiple databases of different years and these databases have same tables so the only difference is the year (..., DB2016, DB2017). In the
The thing that is probably most suitable to your needs here is Spring's AbstractRoutingDataSource
. You do need to define multiple DataSources but you will only need a single repository. Multiple data sources is not an issue here as there is always a way to create the DataSource beans programatically at run time and register them with the application context.
How it works is you basically register a Map<Object, DataSource>
inside your @Configuration class when creating your AbstractRoutingDataSource
@Bean
and in this case the lookup key would be the year.
Then you need create a class that implements AbstractRoutingDataSource and implement the determineCurrentLookupKey()
method. Anytime a database call is made, this method is called in the current context to lookup which DataSource
should be returned. In your case it sounds like you simply want to have the year as a @PathVariable
in the URL and then as the implementation of determineCurrentLookupKey()
grab that @PathVariable
out of the URL (e.g in your controller you have mappings like @GetMapping("/{year}/foo/bar/baz")
).
HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder
.getRequestAttributes()).getRequest();
HashMap templateVariables =
(HashMap)request.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
return templateVariables.get("year");
I used this approach when writing a testing tool for a product where there were many instances running on multiple different servers and I wanted a unified programming model from my @Controller
s but still wanted it to be hitting the right database for the server/deployment combination in the url. Worked like a charm.
The drawback if you are using Hibernate is that all connections will go through a single SessionFactory which will mean you can't take advantage of Hibernate's 2nd level caching as I understand it, but I guess that depends on your needs.