Spring Boot - Change connection dynamically

前端 未结 1 1007
一个人的身影
一个人的身影 2021-01-19 08:00

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

相关标签:
1条回答
  • 2021-01-19 08:18

    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 @Controllers 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.

    0 讨论(0)
提交回复
热议问题