Greifen Sie in mehreren Spring-Boot-Anwendungen auf dieselbe In-Memory-H2-Datenbank zu

Greifen Sie in mehreren Spring Boot-Anwendungen auf dieselbe speicherinterne H2-Datenbank zu

1. Überblick

In diesem kurzen Tutorial zeigen wirhow to access the same in-memory H2 database from multiple Spring Boot applications.

Zu diesem Zweck erstellen wir zwei unterschiedliche Spring Boot-Anwendungen. Die erste Spring Boot-Anwendung startet eine speicherinterne H2-Instanz, während die zweite über TCP auf eine eingebettete H2-Instanz der ersten Anwendung zugreift.

2. Hintergrund

Wie wir wissen, ist eine In-Memory-Datenbank schneller und wird häufig in einem eingebetteten Modus in einer Anwendung verwendet. Die In-Memory-Datenbank behält jedoch keine Daten bei Neustarts des Servers bei.

Weitere Hintergrundinformationen finden Sie in unseren Artikeln zuthe most commonly used in-memory databases undusage of an in-memory database in automated testing.

3. Die Maven-Abhängigkeiten

Die beiden Spring Boot-Anwendungen in diesem Artikel erfordern dieselben Abhängigkeiten:


    
        org.springframework.boot
        spring-boot-starter-data-jpa
    
    
        com.h2database
        h2
    

4. Einrichten der H2-Datenquelle

Definieren wir zunächst die wichtigste Komponente - eine Spring Bean für eine speicherinterne H2-Datenbank - und legen sie über einen TCP-Port offen:

@Bean(initMethod = "start", destroyMethod = "stop")
public Server inMemoryH2DatabaseaServer() throws SQLException {
    return Server.createTcpServer(
      "-tcp", "-tcpAllowOthers", "-tcpPort", "9090");
}

Die durch die ParameterinitMethod unddestroyMethod definierten Methoden werden von Spring aufgerufen, um die H2-Datenbank zu starten und zu stoppen.

Der Parameter-tcp weist H2 an, einen TCP-Server zum Starten von H2 zu verwenden. Wir geben den TCP-Port an, der im dritten und vierten Parameter dercreateTcpServer-Methode verwendet werden soll.

Der ParametertcpAllowOthers öffnet H2 für den Zugriff von externen Anwendungen, die auf demselben Host oder Remote-Hosts ausgeführt werden.

Als Nächstes erstellen wiroverride the default data source, die durch die automatische Konfigurationsfunktion von Spring Boot erstellt wurden, indem wir derapplication.properties-Datei einige Eigenschaften hinzufügen:

spring.datasource.url=jdbc:h2:mem:mydb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.jpa.hibernate.ddl-auto=create

Es ist wichtig, diese Eigenschaften zu überschreiben, dawe’ll need to use the same properties and values in the other applicationsdieselbe H2-Datenbank verwenden möchten.

5. Bootstrapping der ersten Spring Boot-Anwendung

Um unsere Spring Boot-Anwendung zu booten, erstellen wir als Nächstes eine Klasse mit der Sannotation@SpringBootApplication :

@SpringBootApplication
public class SpringBootApp {
    public static void main(String[] args) {
        SpringApplication.run(SpringBootApp.class, args);
    }
}

Um zu testen, ob alles richtig verkabelt ist, fügen wir Code hinzu, um einige Testdaten zu erstellen.

Wir definieren eine Methode mit dem NameninitDb und kommentieren sie mit@PostConstruct , damit der Spring-Container diese Methode automatisch aufruft, sobald die Hauptklasse initialisiert wird:

@PostConstruct
private void initDb() {
    String sqlStatements[] = {
      "drop table employees if exists",
      "create table employees(id serial,first_name varchar(255),last_name varchar(255))",
      "insert into employees(first_name, last_name) values('Eugen','Paraschiv')",
      "insert into employees(first_name, last_name) values('Scott','Tiger')"
    };

    Arrays.asList(sqlStatements).forEach(sql -> {
        jdbcTemplate.execute(sql);
    });

    // Query test data and print results
}

6. Die zweite Spring Boot-Anwendung

Schauen wir uns nun die Komponenten der Clientanwendung an, für die dieselben Maven-Abhängigkeiten wie oben definiert erforderlich sind.

Zunächst überschreiben wir die Datenquelleneigenschaften. Wir müssenensure that the port number in the JDBC URL is the same as the one on which H2 is listening for incoming connections in the first application.

Hier ist dieapplication.properties-Datei der Clientanwendung:

spring.datasource.url=jdbc:h2:tcp://localhost:9090/mem:mydb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.jpa.hibernate.ddl-auto=create

Zuletzt erstellen wir eine Hauptklasse der Client-Spring-Boot-Anwendung.

Der Einfachheit halber definieren wir wieder eine@SpringBootApplication -Scontainingan initDb-Methode mit@PostConstruct annotation:

@SpringBootApplication
public class ClientSpringBootApp {
    public static void main(String[] args) {
        SpringApplication.run(ClientSpringBootApp.class, args);
    }

    @PostConstruct
    private void initDb() {
        String sqlStatements[] = {
          "insert into employees(first_name, last_name) values('Donald','Trump')",
          "insert into employees(first_name, last_name) values('Barack','Obama')"
        };

        Arrays.asList(sqlStatements).forEach(sql -> {
            jdbcTemplate.execute(sql);
        });

        // Fetch data using SELECT statement and print results
    }
}

7. Beispielausgabe

Wenn wir nun beide Anwendungen nacheinander ausführen, können wir die Konsolenprotokolle überprüfen und sicherstellen, dass die zweite Anwendung die Daten wie erwartet druckt.

Hier sind dieconsole logs of the first Spring Boot application:

****** Creating table: Employees, and Inserting test data ******
drop table employees if exists
create table employees(id serial,first_name varchar(255),last_name varchar(255))
insert into employees(first_name, last_name) values('Eugen','Paraschiv')
insert into employees(first_name, last_name) values('Scott','Tiger')
****** Fetching from table: Employees ******
id:1,first_name:Eugen,last_name:Paraschiv
id:2,first_name:Scott,last_name:Tiger

Und hier sind dieconsole logs of the second Spring Boot application:

****** Inserting more test data in the table: Employees ******
insert into employees(first_name, last_name) values('Donald','Trump')
insert into employees(first_name, last_name) values('Barack','Obama')
****** Fetching from table: Employees ******
id:1,first_name:Eugen,last_name:Paraschiv
id:2,first_name:Scott,last_name:Tiger
id:3,first_name:Donald,last_name:Trump
id:4,first_name:Barack,last_name:Obama

8. Fazit

In diesem kurzen Artikel haben wir gesehen, wie wiraccess the same in-memory H2 database instance from multiple Spring Boot applications können.

Wie immer sind Arbeitscodebeispieleover on GitHub verfügbar.