2016-09-29 2 views
0

Для моего нового проекта я построил базовый rest api для возврата данных по запросу клиента. Тем не менее, клиент должен выбрать базу данных по своему выбору в качестве параметра запроса HTTP GET.(Spring-boot & Spring data jpa) Как изменить источник данных на лету?

Теперь мой вопрос в том, что я не знаю, как это сделать с помощью Sprint-boot. Я знаю, что мы можем предоставить много разных источников данных, но как мы можем изменить нужный источник данных после проверки запроса?

Вот мои источники данных конфигурации, которая работает хорошо:

@Configuration 
public class DataSourceConfig { 

    @Bean 
    @Primary 
    @ConfigurationProperties(prefix="datasource.dev21") 
    public DataSource dev21DataSource() throws SQLException { 
     return DataSourceBuilder.create().build(); 
    } 

    @Bean 
    @ConfigurationProperties(prefix="datasource.dev22") 
    public DataSource dev22DataSource() throws SQLException { 
     return DataSourceBuilder.create().build(); 
    } 
} 

Если я хочу, чтобы переключаться между dev21 и dev22 динамически, что я должен делать? Я прочитал статьи о классе AbstractRoutingDataSource, но я не знаю, как его использовать.

+0

Пожалуйста, посмотрите здесь: [Dynamic переключение соединения с базой данных и многоуровневое применение приложений с маршрутизацией базы данных] (http://springrules.blogspot.com/2017/08/dynamic-database-co switching.html-ть соединение) – vRaptor

ответ

0

Без испытав его, и только глядя кратко через Javadoc, что-то подобное может работать

@Configuration 
public class DataSourceConfig { 

    public DataSource dev21DataSource() throws SQLException { 
     return DataSourceBuilder.create().build(); 
    } 

    public DataSource dev22DataSource() throws SQLException { 
     return DataSourceBuilder.create().build(); 
    } 

    @Bean 
    public DataSource dataSource() throws SQLException { 
     RoutingDataSource ds = new RoutingDataSource(); 

     DataSource ds21 = dev21DataSource(); 
     DataSource ds22 = dev22DataSource(); 

     Map dataSources = new HashMap(); 
     dataSources.put(1, ds21); 
     dataSources.put(2, ds22); 

     ds.setDefaultTargetDataSource(ds21); 
     ds.setTargetDataSources(dataSources); 

     return ds; 
    } 
} 

public class RoutingDataSource extends AbstractRoutingDataSource { 

    @Override 
    protected Object determineCurrentLookupKey() { 
     if (true) { //Should probably be some thread/tracaction/request safe check 
      return 1; 
     } else { 
      return 2; 
     } 
    } 
} 

Вы можете override другим способом, если вам нужно другое поведение класса.

0

Она должна идти по линии этого:

// create class to hold the "key" to choose your datasource 
// you will determine it from your GET or POST request 
// It uses ThreadLocal so you will get one per each request 
public class SomeRequestContext { 
    private static ThreadLocal<Object> keyToChoseDataSource = new ThreadLocal<>(); 
    public static void setKeyToChoseDataSource(Object key) { 
     keyToChoseDataSource.set(key); 
    } 
    public static Object getKeyToChoseDataSource() { 
     return keyToChoseDataSource.get(); 
    } 
} 

// This is you AbstractRoutingDataSource implementation that will 
// get the key out of the context class above 
public class MultiDataSource extends AbstractRoutingDataSource { 
    @Override 
    protected Object determineCurrentLookupKey() { 
     return SomeRequestContext.getKeyToChoseDataSource(); 
    } 
} 

И в конфигурации:

// Here you just put all your data sources into the AbstractRoutingDataSource implementation 
    @Bean 
    @Primary 
    public DataSource dataSource() { 
     MultiDataSource dataSource = new MultiDataSource(); 
     dataSource.setDefaultTargetDataSource(someDefaultDataSource()); 
     Map<Object,DataSource> resolvedDataSources = new HashMap<Object,DataSource>(); 
     resolvedDataSources.put("dev21",buildDataSource21()); 
     resolvedDataSources.put("dev22",buildDataSource22()); 
     // ...etc... 
     dataSource.setTargetDataSources(resolvedDataSources); 
     dataSource.afterPropertiesSet(); 
     return dataSource; 
    } 

И в контроллере

@Controller 
public class YourController { 
    @Autowired 
    private YourRepository yourRepository; 
    @RequestMapping(path = "/path", method= RequestMethod.POST) 
    public ResponseEntity<?> createStuff() { 
     TenantContext.setCurrentTenant(tenantName); 
     SomeRequestContext.setKeyToChoseDataSource(getKeyFromRequest()); // this will be dev21 or dev22 or whatever 

     SomeStuff stuff = new SomeStuff(); 
     yourRepository.save(stuff); // will be saved to the correct database 
     return ResponseEntity.ok(stuff); 
    } 
}