2017-05-02 6 views
2

Ich arbeite an meinem Problem für eine sehr lange Zeit und ich kann keine richtige Lösung für mein Problem finden.Spring Boot - Mehrere Datenbankzugriff (MYSQL)

Ich brauche sequentiellen Zugriff auf verschiedene Datenbanken. Ich habe versucht, den Link zu den Datenbanken zu ändern, wie Sie im folgenden Code sehen können.

public static void changeDB(String dbname) throws IOException{ 

    File f = new File("application.properties"); 
    if (f.exists()) { 
     f.delete(); 
    } 
    f.createNewFile(); 
    System.out.println("gelöscht"); 


    FileWriter fw = new FileWriter("application.properties"); 
    BufferedWriter bw = new BufferedWriter(fw); 

    String dbchanger = "spring.datasource.url = jdbc:mysql://localhost:3306/kamis" + dbname; 

    bw.write("server.port = 8000"); 
    bw.write("\n"); 
    bw.write(dbchanger); 
    bw.write("\n"); 
    bw.write("spring.datasource.username=root"); 
    bw.write("\n"); 
    bw.write("spring.datasource.password="); 
    bw.write("\n"); 
    bw.write("spring.datasource.driver-class-name = com.mysql.jdbc.Driver"); 
    bw.write("\n"); 
    bw.write("spring.jpa.database-platform=org.hibernate.dialect.MySQL5Dialect"); 
    bw.write("\n"); 
    bw.write("spring.jpa.hibernate.ddl-auto=update"); 
    bw.write("\n"); 
    bw.write("spring.devtools.livereload.enabled=true"); 

    bw.close(); 
    System.out.println("neu erstellt"); 

} 

Dies funktioniert in gewisser Weise bisher. Das Problem ist, dass die Anwendung neu geladen werden muss, um die Änderungen aus meiner application.properties zu lesen, um eine Verbindung mit der anderen Datenbank herzustellen, was für mich keine wirkliche Lösung ist, da die Anwendung neu gestartet wird. Es muss auch dynamisch veränderbar sein, weil ich mit mehr als 30 Datenbanken arbeite.

Vielleicht können Sie mir helfen, herauszufinden, wie Sie es neu laden oder vielleicht geben Sie mir eine passendere Lösung für mein Problem.

Vielen Dank im Voraus. Kai

Antwort

0

Sie können mehrere DataSource-Objekte in Ihrer Spring-Konfiguration definieren und die gewünschte verwenden.

Markieren Sie beide Datenquellen als @Bean. Außerdem müssen Sie zwei EntitYManager definieren (jeder basiert auf seiner eigenen DataSource).

Lesen the example für weitere Informationen

UPDATE: Für den Fall, dass ich Proxy Datasource-Implementierung würde die Logik zu halten. Die Idee ist, DataSource-Schnittstelle zu implementieren, die intern eine Zuordnung von DataSources haben kann. (Schlüssel ist z.B. JDBC URL + Benutzername)

Anfangs ist die Karte leer. Beim ersten Aufruf prüfen wir, ob es in der Map eine Instanz für den angegebenen Benutzer gibt. Wenn nicht, erstellen wir eine neue DataSource-Instanz im Fly und platzieren sie in der Map. Alle ProxyDataSource-Methoden erhalten (oder erstellen) nur die delegierenden benutzerspezifischen DataSource-Instanzen und rufen dieselbe Methode der Benutzerinstanz auf.

Sie deklarieren @Bean DataSource, die die ProxyDataSource zurückgibt, die intern die Logik verarbeitet.

+0

ich mit Ihnen dort zustimmen. Vielleicht habe ich vergessen zu erwähnen, dass jeder Benutzer eine neue Datenbank erstellen kann, wenn er einen neuen Kanal für mein Programm erstellt und dieser für ungefähr 100-200 Personen gleichzeitig laufen soll. Die Lösung, die Sie mir geben, dass ich diese Dinge nicht für jeden schreiben kann. – Kai

+0

Die Antwort wurde aktualisiert. – StanislavL

+0

Klingt gut an erster Stelle. Hast du ein Beispiel oder eine Seite, wo ich mehr darüber lesen kann? Danke – Kai

1

Sie können die folgende Konfiguration verwenden, die ich verwendet habe, um mehrere Datenbanken im Spring Boot zu verwenden. Application.properties:-

server.port=6060 
spring.ds_post.url =jdbc:postgresql://localhost:5432/kode12 
spring.ds_post.username =postgres 
spring.ds_post.password =root 
spring.ds_post.driverClassName=org.postgresql.Driver 
spring.ds_mysql.url = jdbc:mysql://localhost:3306/kode12 
spring.ds_mysql.username = root 
spring.ds_mysql.password = root 
spring.ds_mysql.driverClassName=com.mysql.jdbc.Driver 

MultipleDBConfig.java

@Configuration 
public class MultipleDBConfig { 
    @Bean(name = "mysqlDb") 
    @ConfigurationProperties(prefix = "spring.ds_mysql") 
    public DataSource mysqlDataSource() { 
     return DataSourceBuilder.create().build(); 
    } 

    @Bean(name = "mysqlJdbcTemplate") 
    public JdbcTemplate jdbcTemplate(@Qualifier("mysqlDb") DataSource dsMySQL) { 
     return new JdbcTemplate(dsMySQL); 
    } 

    @Bean(name = "postgresDb") 
    @ConfigurationProperties(prefix = "spring.ds_post") 
    public DataSource postgresDataSource() { 
     return DataSourceBuilder.create().build(); 
    } 

    @Bean(name = "postgresJdbcTemplate") 
    public JdbcTemplate postgresJdbcTemplate(@Qualifier("postgresDb") 
               DataSource dsPostgres) { 
     return new JdbcTemplate(dsPostgres); 
    } 
} 

Dies ist die kommentierte Konfigurationsklasse, die Funktionen enthält, und Anmerkungen für unsere PostgreSQL und MySQL-Konfiguration geladen werden. Es ist auch verantwortlich für das Erstellen einer JDBCTemplate-Instanz für jede.

+0

Vielen Dank für Ihre Antwort, aber das ist in meinem Fall auch nicht sehr passend, da ich bereits 30 Datenbanken habe. Man kann sie nicht alle manuell eingeben, da täglich mehr da ist. Vielleicht hast du eine andere Idee. – Kai

+0

meinst du es ernst. In diesem Szenario müssen Sie auch die Datenbank-URL, den Benutzernamen und das Kennwort für jede von ihnen in application.properties definieren, da es hierfür keine Alternative gibt. und auch Bean, die Sie definieren müssen, um auf diese Datenbank zuzugreifen. Dennoch werde ich nach einer passenden Antwort suchen und Sie wissen lassen. Wir werden dieses Problem definitiv knacken. Danke –

+0

yeah sadly im serious :) Danke, dass du optimistisch bist, weil ich langsam das Gefühl habe aufzugeben. – Kai

0

Scheint, wie Sie ein Multi-Tenant-Ansatz implementieren könnte, Thema, das ich in einem Blog vor ein paar Monaten nach abgedeckt: Multi-tenant applications using Spring Boot, JPA, Hibernate and Postgres

Die Schritte, um die Persistenz-Schicht für Multitenancy Unterstützung zu konfigurieren umfasst:

  • Hibernate-, JPA- und Datenquelleneigenschaften. Etwas wie:

application.yml

... 
multitenancy: 
    dvdrental: 
    dataSources: 
     - 
     tenantId: TENANT_01 
     url: jdbc:postgresql://172.16.69.133:5432/db_dvdrental 
     username: user_dvdrental 
     password: changeit 
     driverClassName: org.postgresql.Driver 
     - 
     tenantId: TENANT_02 
     url: jdbc:postgresql://172.16.69.133:5532/db_dvdrental 
     username: user_dvdrental 
     password: changeit 
     driverClassName: org.postgresql.Driver 
... 

Ich benutzte eine Eigenschaften zum Speichern von Mieterdaten-Datei, aber diese angepasst werden könnte Mieterinformationen in einer Art Master-DB zu speichern.

MultiTenantJpaConfiguration.java

... 
@Configuration 
@EnableConfigurationProperties({ MultiTenantDvdRentalProperties.class, JpaProperties.class }) 
@ImportResource(locations = { "classpath:applicationContent.xml" }) 
@EnableTransactionManagement 
public class MultiTenantJpaConfiguration { 

    @Autowired 
    private JpaProperties jpaProperties; 

    @Autowired 
    private MultiTenantDvdRentalProperties multiTenantDvdRentalProperties; 
... 
} 

MultiTenantDvdRentalProperties.java

... 
@Configuration 
@ConfigurationProperties(prefix = "multitenancy.dvdrental") 
public class MultiTenantDvdRentalProperties { 

    private List<DataSourceProperties> dataSourcesProps; 
    // Getters and Setters 

    public static class DataSourceProperties extends org.springframework.boot.autoconfigure.jdbc.DataSourceProperties { 

    private String tenantId; 
    // Getters and Setters 
    } 
} 
  • Datenquellen Bohnen

MultiTenantJpaConfiguration.java

... 
public class MultiTenantJpaConfiguration { 
... 
    @Bean(name = "dataSourcesDvdRental") 
    public Map<String, DataSource> dataSourcesDvdRental() { 
     ... 
    } 
... 
} 
  • Entity Manager Fabrik Bohne

MultiTenantJpaConfiguration.java

... 
public class MultiTenantJpaConfiguration { 
... 
    @Bean 
    public MultiTenantConnectionProvider multiTenantConnectionProvider() { 
     ... 
    } 

    @Bean 
    public CurrentTenantIdentifierResolver currentTenantIdentifierResolver() { 
     ... 
    } 

    @Bean 
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean(MultiTenantConnectionProvider multiTenantConnectionProvider, 
    CurrentTenantIdentifierResolver currentTenantIdentifierResolver) { 
     ... 
    } 
... 
} 
  • Transaktionsmanager Bohne

MultiTenantJpaConfiguration.java

... 
public class MultiTenantJpaConfiguration { 
... 
    @Bean 
    public EntityManagerFactory entityManagerFactory(LocalContainerEntityManagerFactoryBean entityManagerFactoryBean) { 
     ... 
    } 

    @Bean 
    public PlatformTransactionManager txManager(EntityManagerFactory entityManagerFactory) { 
     ... 
    } 
... 
} 
  • Spring Data JPA und Transaktionsunterstützung Konfiguration

applicationContent.xml

... 
<jpa:repositories base-package="com.asimio.dvdrental.dao" transaction-manager-ref="txManager" /> 
<tx:annotation-driven transaction-manager="txManager" proxy-target-class="true" /> 
... 

ActorDao. java

public interface ActorDao extends JpaRepository<Actor, Integer> { 
} 

Je nach Bedarf etwas wie dies geschehen könnte:

... 
@Autowired 
private ActorDao actorDao; 
... 

DvdRentalTenantContext.setTenantId("TENANT_01"); 
this.actorDao.findOne(...); 
... 

// Or 
DvdRentalTenantContext.setTenantId("TENANT_02"); 
this.actorDao.save(...); 
... 

die tenantId Einstellung in einem Servlet-Filter/Spring MVC Abfangjäger getan werden könnte/Thread, der die JPA ausführen wird Betrieb usw.

Wieder eine detaillierte Erklärung und Quellcode könnte unter: Multi-tenant applications using Spring Boot, JPA, Hibernate and Postgres