2016-09-29 2 views
0

Für mein neues Projekt, ich baute eine grundlegende Ruhe-API, um Daten auf die Client-Anfrage zurückzugeben. Der Client muss jedoch die Datenbank seiner Wahl als Parameter der HTTP-GET-Anforderung auswählen.(Spring-Boot & Spring-Daten jpa) Wie ändere ich die Datenquelle im laufenden Betrieb?

Nun meine Frage ist, dass ich weiß nicht, wie das mit Sprint-Boot zu tun. Ich weiß, dass wir viele verschiedene Datenquellen bereitstellen können, aber wie können wir die gewünschte Datenquelle nach der Überprüfung der Anfrage ändern?

Hier ist meine Datenquellen Config, die gut funktioniert:

@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(); 
    } 
} 

Wenn ich dynamisch, was soll ich tun zwischen dev21 und dev22 wechseln? Ich habe Artikel über die Klasse AbstractRoutingDataSource gelesen, aber ich weiß nicht, wie man es benutzt.

+0

Bitte sehen Sie hier: [Dynamische Datenbank-Verbindungswechsel und Anwendung Multitenancy mit Datenbank-Routing] (http://springrules.blogspot.com/2017/08/dynamic-database-co Verbindung-Schaltung.html) – vRaptor

Antwort

0

Ohne sie getestet haben, und nur kurz durch die javadoc, so etwas wie dies könnte

@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; 
     } 
    } 
} 

Vielleicht möchten Sie override andere Methode suchen arbeiten, wenn Sie aus der Klasse anderes Verhalten benötigen.

0

Es sollte nach dem Vorbild der gehen:

// 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(); 
    } 
} 

Und in Ihrer Konfiguration:

// 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; 
    } 

Und in Ihrem Controller

@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); 
    } 
} 
Verwandte Themen