Verwenden von Spring Data R2DBC mit Azure Database for PostgreSQL
In diesem Artikel wird die Erstellung einer Beispielanwendung veranschaulicht, die Spring Data R2DBC verwendet, um Informationen in einer Azure Database for PostgreSQL-Datenbank zu speichern bzw. daraus abzurufen. Im Beispiel wird die R2DBC-Implementierung für PostgreSQL aus dem r2dbc-postgresql-Repository auf GitHub verwendet.
R2DBC ermöglicht die Nutzung reaktiver APIs mit herkömmlichen relationalen Datenbanken. Sie können es zusammen mit Spring WebFlux verwenden, um vollständig reaktive Spring Boot-Anwendungen zu erstellen, die nicht blockierende APIs verwenden. Dies bietet bessere Skalierbarkeit als der klassische „Ein-Thread-pro-Verbindung“-Ansatz.
Voraussetzungen
Azure-Abonnement (kostenloses Abonnement erstellen)
Java Development Kit (JDK), Version 8 oder höher.
cURL oder ein ähnliches HTTP-Hilfsprogramm zum Testen der Funktionalität.
Siehe die Beispielanwendung
In diesem Artikel wird eine Beispielanwendung codiert. Wenn Sie schneller vorgehen möchten, ist diese Anwendung unter https://github.com/Azure-Samples/quickstart-spring-data-r2dbc-postgresql bereits programmiert und verfügbar.
Vorbereiten der Arbeitsumgebung
Richten Sie zunächst einige Umgebungsvariablen ein, indem Sie die folgenden Befehle ausführen:
export AZ_RESOURCE_GROUP=database-workshop
export AZ_DATABASE_SERVER_NAME=<YOUR_DATABASE_SERVER_NAME>
export AZ_DATABASE_NAME=<YOUR_DATABASE_NAME>
export AZ_LOCATION=<YOUR_AZURE_REGION>
export AZ_POSTGRESQL_ADMIN_USERNAME=spring
export AZ_POSTGRESQL_ADMIN_PASSWORD=<YOUR_POSTGRESQL_ADMIN_PASSWORD>
export AZ_POSTGRESQL_NON_ADMIN_USERNAME=nonspring
export AZ_POSTGRESQL_NON_ADMIN_PASSWORD=<YOUR_POSTGRESQL_NON_ADMIN_PASSWORD>
export AZ_LOCAL_IP_ADDRESS=<YOUR_LOCAL_IP_ADDRESS>
Ersetzen Sie die Platzhalter durch die folgenden Werte, die in diesem Artikel verwendet werden:
<YOUR_DATABASE_SERVER_NAME>
: Der Name Ihres PostgreSQL-Servers, der in Azure eindeutig sein muss.<YOUR_DATABASE_NAME>
: Der Datenbankname Ihres PostgreSQL-Servers, der in Azure eindeutig sein muss.<YOUR_AZURE_REGION>
: Die von Ihnen verwendete Azure-Region. Sie können standardmäßigeastus
verwenden, wir empfehlen aber, eine Region zu konfigurieren, die näher an Ihrem Standort liegt. Sie können die vollständige Liste der verfügbaren Regionen mithilfeaz account list-locations
von .<YOUR_POSTGRESQL_ADMIN_PASSWORD>
und<YOUR_POSTGRESQL_NON_ADMIN_PASSWORD>
: Das Kennwort Ihres PostgreSQL-Datenbankservers, das mindestens acht Zeichen enthalten sollte. Es muss Zeichen aus drei der folgenden Kategorien enthalten: Englische Großbuchstaben, englische Kleinbuchstaben, Zahlen (0-9) und nicht alphanumerische Zeichen (!, $, #, % usw.).<YOUR_LOCAL_IP_ADDRESS>
: Die IP-Adresse Ihres lokalen Computers, auf dem Sie die Spring Boot-Anwendung ausführen. Sie können sie ganz einfach ermitteln, indem Sie whatismyip.akamai.com öffnen.
Hinweis
Microsoft empfiehlt, immer den sichersten Authentifizierungsflow zu verwenden, der verfügbar ist. Der in diesem Verfahren beschriebene Authentifizierungsfluss, z. B. für Datenbanken, Caches, Nachrichten oder KI-Dienste, erfordert ein sehr hohes Vertrauen in die Anwendung und trägt Risiken, die in anderen Flüssen nicht vorhanden sind. Verwenden Sie diesen Fluss nur, wenn sicherere Optionen wie verwaltete Identitäten für kennwortlose oder schlüssellose Verbindungen nicht geeignet sind. Bei Vorgängen des lokalen Computers bevorzugen Sie Benutzeridentitäten für kennwortlose oder schlüssellose Verbindungen.
Erstellen Sie nun mithilfe des folgenden Befehls eine Ressourcengruppe:
az group create \
--name $AZ_RESOURCE_GROUP \
--location $AZ_LOCATION \
--output tsv
Erstellen einer Azure-Datenbank für Die PostgreSQL-Instanz und Einrichten des Administratorbenutzers
Als Erstes erstellen Sie einen verwalteten PostgreSQL-Server mit einem Administratorbenutzer.
Hinweis
Ausführlichere Informationen zum Erstellen von PostgreSQL-Servern finden Sie unter Erstellen eines Azure Database for PostgreSQL-Servers im Azure-Portal.
az postgres flexible-server create \
--resource-group $AZ_RESOURCE_GROUP \
--name $AZ_DATABASE_SERVER_NAME \
--location $AZ_LOCATION \
--admin-user $AZ_POSTGRESQL_ADMIN_USERNAME \
--admin-password $AZ_POSTGRESQL_ADMIN_PASSWORD \
--yes \
--output tsv
Konfigurieren einer PostgreSQL-Datenbank
Der von Ihnen zuvor erstellte PostgreSQL-Server ist leer. Erstellen Sie mit dem folgenden Befehl eine neue Datenbank:
az postgres flexible-server db create \
--resource-group $AZ_RESOURCE_GROUP \
--database-name $AZ_DATABASE_NAME \
--server-name $AZ_DATABASE_SERVER_NAME \
--output tsv
Konfigurieren einer Firewallregel für den PostgreSQL-Server
Azure Database for PostgreSQL-Instanzen sind standardmäßig gesichert. Sie besitzen eine Firewall, die keine eingehenden Verbindungen zulässt. Damit Sie die Datenbank verwenden können, müssen Sie eine Firewallregel hinzufügen, die den Zugriff der lokalen IP-Adresse auf den Datenbankserver zulässt.
Da Sie die lokale IP-Adresse zu Beginn dieses Artikels konfiguriert haben, können Sie die Firewall des Servers öffnen, indem Sie den folgenden Befehl ausführen:
az postgres flexible-server firewall-rule create \
--resource-group $AZ_RESOURCE_GROUP \
--name $AZ_DATABASE_SERVER_NAME \
--rule-name $AZ_DATABASE_SERVER_NAME-database-allow-local-ip \
--start-ip-address $AZ_LOCAL_IP_ADDRESS \
--end-ip-address $AZ_LOCAL_IP_ADDRESS \
--output tsv
Wenn Sie über das Windows-Subsystem für Linux (WSL) auf einem Windows-Computer eine Verbindung mit Ihrem PostgreSQL-Server herstellen, müssen Sie der Firewall die WSL-Host-ID hinzufügen.
Rufen Sie die IP-Adresse Ihres Hostcomputers ab, indem Sie den folgenden Befehl in WSL ausführen:
cat /etc/resolv.conf
Kopieren Sie die IP-Adresse nach dem Ausdruck nameserver
, und verwenden Sie dann den folgenden Befehl, um eine Umgebungsvariable für die WSL-IP-Adresse festzulegen:
export AZ_WSL_IP_ADDRESS=<the-copied-IP-address>
Verwenden Sie dann den folgenden Befehl, um die Firewall des Servers für Ihre WSL-basierte App zu öffnen:
az postgres flexible-server firewall-rule create \
--resource-group $AZ_RESOURCE_GROUP \
--name $AZ_DATABASE_SERVER_NAME \
--rule-name $AZ_DATABASE_SERVER_NAME-database-allow-local-ip \
--start-ip-address $AZ_WSL_IP_ADDRESS \
--end-ip-address $AZ_WSL_IP_ADDRESS \
--output tsv
Erstellen eines PostgreSQL-Nicht-Administratorbenutzers und Erteilen von Berechtigungen
Erstellen Sie nun einen Nicht-Administratorbenutzer, und gewähren Sie ihm alle Berechtigungen für die Datenbank.
Hinweis
Ausführlichere Informationen zum Erstellen von PostgreSQL-Benutzern finden Sie unter Erstellen von Benutzern in Azure Database for PostgreSQL.
Erstellen Sie ein SQL-Skript namens create_user.sql zum Erstellen eines Nicht-Administratorbenutzers. Fügen Sie den folgenden Inhalt hinzu, und speichern Sie das Skript lokal:
Hinweis
Microsoft empfiehlt, immer den sichersten Authentifizierungsflow zu verwenden, der verfügbar ist. Der in diesem Verfahren beschriebene Authentifizierungsfluss, z. B. für Datenbanken, Caches, Nachrichten oder KI-Dienste, erfordert ein sehr hohes Vertrauen in die Anwendung und trägt Risiken, die in anderen Flüssen nicht vorhanden sind. Verwenden Sie diesen Fluss nur, wenn sicherere Optionen wie verwaltete Identitäten für kennwortlose oder schlüssellose Verbindungen nicht geeignet sind. Bei Vorgängen des lokalen Computers bevorzugen Sie Benutzeridentitäten für kennwortlose oder schlüssellose Verbindungen.
cat << EOF > create_user.sql
CREATE ROLE "$AZ_POSTGRESQL_NON_ADMIN_USERNAME" WITH LOGIN PASSWORD '$AZ_POSTGRESQL_NON_ADMIN_PASSWORD';
GRANT ALL PRIVILEGES ON DATABASE $AZ_DATABASE_NAME TO "$AZ_POSTGRESQL_NON_ADMIN_USERNAME";
EOF
Verwenden Sie dann den folgenden Befehl, um das SQL-Skript zum Erstellen des/der Microsoft Entra-Benutzers/-Benutzerin ohne Administratorrechte auszuführen:
psql "host=$AZ_DATABASE_SERVER_NAME.postgres.database.azure.com user=$AZ_POSTGRESQL_ADMIN_USERNAME dbname=$AZ_DATABASE_NAME port=5432 password=$AZ_POSTGRESQL_ADMIN_PASSWORD sslmode=require" < create_user.sql
Verwenden Sie nun den folgenden Befehl, um die temporäre SQL-Skriptdatei zu entfernen:
rm create_user.sql
Erstellen einer reaktiven Spring Boot-Anwendung
Zum Erstellen einer reaktiven Spring Boot-Anwendung wird Spring Initializr verwendet. Die von uns erstellte Anwendung verwendet Folgendes:
- Spring Boot 2.7.11.
- Die folgenden Abhängigkeiten: Spring Reactive Web (auch als Spring WebFlux bezeichnet) und Spring Data R2DBC.
Erstellen der Anwendung mithilfe von Spring Initializr
Generieren Sie die Anwendung mithilfe des folgenden Befehls in der Befehlszeile:
curl https://start.spring.io/starter.tgz -d dependencies=webflux,data-r2dbc -d baseDir=azure-database-workshop -d bootVersion=2.7.11 -d javaVersion=17 | tar -xzvf -
Hinzufügen der reaktiven PostgreSQL-Treiberimplementierung
Öffnen Sie die Datei pom.xml des generierten Projekts, um den reaktiven PostgreSQL-Treiber aus dem Repository „r2dbc-postgresql“ auf GitHub hinzuzufügen. Fügen Sie nach der Abhängigkeit spring-boot-starter-webflux
den folgenden Text hinzu:
<dependency>
<groupId>io.r2dbc</groupId>
<artifactId>r2dbc-postgresql</artifactId>
<version>0.8.12.RELEASE</version>
<scope>runtime</scope>
</dependency>
Konfigurieren von Spring Boot für die Verwendung von Azure Database for PostgreSQL
Öffnen Sie die Datei src/main/resources/application.properties, und fügen Sie den folgenden Text hinzu:
logging.level.org.springframework.data.r2dbc=DEBUG
spring.r2dbc.url=r2dbc:pool:postgres://$AZ_DATABASE_SERVER_NAME.postgres.database.azure.com:5432/$AZ_DATABASE_NAME
spring.r2dbc.username=nonspring
spring.r2dbc.password=$AZ_POSTGRESQL_NON_ADMIN_PASSWORD
spring.r2dbc.properties.sslMode=REQUIRE
Ersetzen Sie die $AZ_DATABASE_SERVER_NAME
, $AZ_DATABASE_NAME
und $AZ_POSTGRESQL_NON_ADMIN_PASSWORD
Variablen durch die Werte, die Sie am Anfang dieses Artikels konfiguriert haben.
Warnung
Aus Sicherheitsgründen erfordert Azure Database for PostgreSQL die Verwendung von SSL-Verbindungen. Daher müssen Sie die Konfigurationseigenschaft spring.r2dbc.properties.sslMode=REQUIRE
hinzufügen. Andernfalls versucht der R2DBC PostgreSQL-Treiber, eine unsichere Verbindung herzustellen, was zu einem Fehler führt.
Hinweis
Zur Verbesserung der Leistung ist die spring.r2dbc.url
-Eigenschaft so konfiguriert, dass ein Verbindungspool mit r2dbc-pool verwendet wird.
Sie sollten Ihre Anwendung nun mithilfe des angegebenen Maven-Wrappers wie folgt starten können:
./mvnw spring-boot:run
Hier sehen Sie einen Screenshot der Anwendung bei der ersten Ausführung:
Erstellen des Datenbankschemas
Konfigurieren Sie in der DemoApplication
-Hauptklasse mit dem folgenden Code eine neue Spring Bean, die ein Datenbankschema erstellt:
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.r2dbc.connectionfactory.init.ConnectionFactoryInitializer;
import org.springframework.data.r2dbc.connectionfactory.init.ResourceDatabasePopulator;
import io.r2dbc.spi.ConnectionFactory;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@Bean
public ConnectionFactoryInitializer initializer(ConnectionFactory connectionFactory) {
ConnectionFactoryInitializer initializer = new ConnectionFactoryInitializer();
initializer.setConnectionFactory(connectionFactory);
ResourceDatabasePopulator populator = new ResourceDatabasePopulator(new ClassPathResource("schema.sql"));
initializer.setDatabasePopulator(populator);
return initializer;
}
}
Diese Spring Bean verwendet eine Datei namens schema.sql. Erstellen Sie daher diese Datei im Ordner src/main/resources, und fügen Sie den folgenden Text hinzu:
DROP TABLE IF EXISTS todo;
CREATE TABLE todo (id SERIAL PRIMARY KEY, description VARCHAR(255), details VARCHAR(4096), done BOOLEAN);
Halten Sie die ausgeführte Anwendung an, und starten Sie sie mit dem folgenden Befehl erneut. Die Anwendung verwendet nun die Datenbank demo
, die Sie zuvor erstellt haben, und erstellt darin eine todo
-Tabelle.
./mvnw spring-boot:run
Hier sehen Sie einen Screenshot der Datenbanktabelle während der Erstellung:
Codieren der Anwendung
Fügen Sie als Nächstes den Java-Code hinzu, der R2DBC zum Speichern und Abrufen von Daten auf bzw. aus Ihrem PostgreSQL-Server verwendet.
Erstellen Sie neben der Klasse DemoApplication
mit dem folgenden Code eine neue Todo
-Java-Klasse:
package com.example.demo;
import org.springframework.data.annotation.Id;
public class Todo {
public Todo() {
}
public Todo(String description, String details, boolean done) {
this.description = description;
this.details = details;
this.done = done;
}
@Id
private Long id;
private String description;
private String details;
private boolean done;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getDetails() {
return details;
}
public void setDetails(String details) {
this.details = details;
}
public boolean isDone() {
return done;
}
public void setDone(boolean done) {
this.done = done;
}
}
Bei dieser Klasse handelt es sich um ein Domänenmodell, das der zuvor erstellten todo
-Tabelle zugeordnet ist.
Sie benötigen ein Repository, um diese Klasse zu verwalten. Definieren Sie mit dem folgenden Code eine neue TodoRepository
-Schnittstelle im gleichen Paket:
package com.example.demo;
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
public interface TodoRepository extends ReactiveCrudRepository<Todo, Long> {
}
Dieses Repository ist ein reaktives Repository, das von Spring Data R2DBC verwaltet wird.
Stellen Sie die Anwendung fertig, indem Sie einen Controller erstellen, der Daten speichern und abrufen kann. Implementieren Sie eine TodoController
-Klasse im gleichen Paket, und fügen Sie den folgenden Code hinzu:
package com.example.demo;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@RestController
@RequestMapping("/")
public class TodoController {
private final TodoRepository todoRepository;
public TodoController(TodoRepository todoRepository) {
this.todoRepository = todoRepository;
}
@PostMapping("/")
@ResponseStatus(HttpStatus.CREATED)
public Mono<Todo> createTodo(@RequestBody Todo todo) {
return todoRepository.save(todo);
}
@GetMapping("/")
public Flux<Todo> getTodos() {
return todoRepository.findAll();
}
}
Halten Sie die Anwendung schließlich an, und starten Sie sie mit dem folgenden Befehl erneut:
./mvnw spring-boot:run
Testen der Anwendung
Zum Testen der Anwendung können Sie cURL verwenden.
Erstellen Sie zunächst mit dem folgenden Befehl ein neues todo-Element in der Datenbank:
curl --header "Content-Type: application/json" \
--request POST \
--data '{"description":"configuration","details":"congratulations, you have set up R2DBC correctly!","done": "true"}' \
http://127.0.0.1:8080
Mit diesem Befehl sollte das erstellte Element wie hier gezeigt zurückgegeben werden:
{"id":1,"description":"configuration","details":"congratulations, you have set up R2DBC correctly!","done":true}
Rufen Sie anschließend die Daten mithilfe einer neuen cURL-Anforderung mit dem folgenden Befehl ab:
curl http://127.0.0.1:8080
Mit dem folgenden Befehl wird wie hier gezeigt die Liste der „todo“-Elemente zurückgegeben, einschließlich des von Ihnen erstellten Elements:
[{"id":1,"description":"configuration","details":"congratulations, you have set up R2DBC correctly!","done":true}]
Hier sehen Sie einen Screenshot dieser cURL-Anforderungen:
Herzlichen Glückwunsch! Sie haben eine vollständig reaktive Spring Boot-Anwendung erstellt, die R2DBC zum Speichern und Abrufen von Daten in bzw. aus Azure Database for PostgreSQL verwendet.
Bereinigen von Ressourcen
Um alle während dieser Schnellstartanleitung verwendeten Ressourcen zu bereinigen, löschen Sie die Ressourcengruppe mithilfe des folgenden Befehls:
az group delete \
--name $AZ_RESOURCE_GROUP \
--yes
Nächste Schritte
Weitere Informationen zum Bereitstellen einer Spring Data-Anwendung für Azure Spring Apps und die Verwendung verwalteter Identitäten finden Sie im Lernprogramm: Bereitstellen einer Spring-Anwendung in Azure Spring Apps mit einer kennwortlosen Verbindung zu einer Azure-Datenbank.
Weitere Informationen zu Spring und Azure finden Sie im Dokumentationscenter zu Spring in Azure.
Siehe auch
Weitere Informationen zu Spring Data R2DBC finden Sie in der Referenzdokumentation zu Spring.
Weitere Informationen zur Verwendung von Azure mit Java finden Sie unter Azure für Java-Entwickler und Working with Azure DevOps and Java (Arbeiten mit Azure DevOps und Java).