Verwenden von Spring Data R2DBC mit Azure SQL-Datenbank

In diesem Artikel wird die Erstellung einer Beispielanwendung veranschaulicht, die Spring Data R2DBC verwendet, um Informationen in Azure SQL-Datenbank mithilfe der R2DBC-Implementierung für Microsoft SQL Server aus dem GitHub-Repository „r2dbc-mssql“ zu speichern und abzurufen.

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

  • sqlcmd Utility.

  • cURL oder ein ähnliches HTTP-Hilfsprogramm zum Testen der Funktionalität.

Sehen Sie sich die Beispielanwendung an

In diesem Artikel codierten Sie eine Beispielanwendung. Wenn Sie schneller vorgehen möchten, ist diese Anwendung unter https://github.com/Azure-Samples/quickstart-spring-data-r2dbc-sql-server bereits programmiert und verfügbar.

Vorbereiten der Arbeitsumgebung

Richten Sie zunächst mithilfe der folgenden Befehle einige Umgebungsvariablen ein:

export AZ_RESOURCE_GROUP=database-workshop
export AZ_DATABASE_NAME=<YOUR_DATABASE_NAME>
export AZ_LOCATION=<YOUR_AZURE_REGION>
export AZ_SQL_SERVER_ADMIN_USERNAME=spring
export AZ_SQL_SERVER_ADMIN_PASSWORD=<YOUR_AZURE_SQL_ADMIN_PASSWORD>
export AZ_SQL_SERVER_NON_ADMIN_USERNAME=nonspring
export AZ_SQL_SERVER_NON_ADMIN_PASSWORD=<YOUR_AZURE_SQL_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_NAME>: Der Name Ihres Azure SQL-Datenbank-Servers, der in Azure eindeutig sein soll.
  • <YOUR_AZURE_REGION>: Die von Ihnen verwendete Azure-Region. Sie können standardmäßig eastus 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 mithilfe az account list-locationsvon .
  • <AZ_SQL_SERVER_ADMIN_PASSWORD>und <AZ_SQL_SERVER_NON_ADMIN_PASSWORD>: Das Kennwort Ihres Azure SQL-Datenbank-Servers, 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.

Erstellen Sie nun mithilfe des folgenden Befehls eine Ressourcengruppe:

az group create \
    --name $AZ_RESOURCE_GROUP \
    --location $AZ_LOCATION \
    --output tsv

Erstellen einer Azure SQL-Datenbankinstanz

Erstellen Sie als Nächstes eine verwaltete Azure SQL-Datenbank Serverinstanz, indem Sie den folgenden Befehl ausführen.

Hinweis

Das MS SQL-Kennwort muss bestimmte Kriterien erfüllen, und das Setup schlägt mit einem nicht kompatiblen Kennwort fehl. Weitere Informationen finden Sie unter Password Policy.

az sql server create \
    --resource-group $AZ_RESOURCE_GROUP \
    --name $AZ_DATABASE_NAME \
    --location $AZ_LOCATION \
    --admin-user $AZ_SQL_SERVER_ADMIN_USERNAME \
    --admin-password $AZ_SQL_SERVER_ADMIN_PASSWORD \
    --output tsv

Konfigurieren einer Firewallregel für den Azure SQL-Datenbank-Server

Azure SQL-Datenbankinstanzen 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 sql server firewall-rule create \
    --resource-group $AZ_RESOURCE_GROUP \
    --name $AZ_DATABASE_NAME-database-allow-local-ip \
    --server $AZ_DATABASE_NAME \
    --start-ip-address $AZ_LOCAL_IP_ADDRESS \
    --end-ip-address $AZ_LOCAL_IP_ADDRESS \
    --output tsv

Wenn Sie eine Verbindung mit Ihrem Azure SQL-Datenbank Server von Windows-Subsystem für Linux (WSL) auf einem Windows-Computer 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 sql server firewall-rule create \
    --resource-group $AZ_RESOURCE_GROUP \
    --name $AZ_DATABASE_NAME-database-allow-local-ip-wsl \
    --server $AZ_DATABASE_NAME \
    --start-ip-address $AZ_WSL_IP_ADDRESS \
    --end-ip-address $AZ_WSL_IP_ADDRESS \
    --output tsv

Konfigurieren einer Azure SQL-Datenbank

Der von Ihnen zuvor erstellte Azure SQL-Datenbank-Server ist leer. Er verfügt über keine Datenbank, die Sie mit der Spring Boot-Anwendung verwenden können. Erstellen Sie durch Ausführen des folgenden Befehls eine neue Datenbank namens demo:

az sql db create \
    --resource-group $AZ_RESOURCE_GROUP \
    --name demo \
    --server $AZ_DATABASE_NAME \
    --output tsv

Erstellen einer SQL-Datenbank, die kein Administrator ist, und Erteilen von Berechtigungen

In diesem Schritt wird ein Nicht-Administrator-Benutzer erstellt und ihm alle Berechtigungen für die demo Datenbank erteilt.

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:

cat << EOF > create_user.sql
USE demo;
GO
CREATE USER $AZ_SQL_SERVER_NON_ADMIN_USERNAME WITH PASSWORD='$AZ_SQL_SERVER_NON_ADMIN_PASSWORD'
GO
GRANT CONTROL ON DATABASE::demo TO $AZ_SQL_SERVER_NON_ADMIN_USERNAME;
GO
EOF

Verwenden Sie dann den folgenden Befehl, um das SQL-Skript auszuführen, um den Nicht-Administratorbenutzer zu erstellen:

sqlcmd -S $AZ_DATABASE_NAME.database.windows.net,1433  -d demo -U $AZ_SQL_SERVER_ADMIN_USERNAME -P $AZ_SQL_SERVER_ADMIN_PASSWORD  -i create_user.sql

Hinweis

Weitere Informationen zum Erstellen von SQL-Datenbankbenutzern finden Sie unter CREATE USER (Transact-SQL).For more information about creating SQL database users, see CREATE USER (Transact-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 durch Ausführen 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 Treiberimplementierung für Azure SQL-Datenbank

Öffnen Sie die Datei pom.xml des generierten Projekts, um den reaktiven Azure SQL-Datenbank-Treiber aus dem GitHub-Repository „r2dbc-mssql“ hinzuzufügen.

Fügen Sie nach der Abhängigkeit spring-boot-starter-webflux den folgenden Text hinzu:

<dependency>
    <groupId>io.r2dbc</groupId>
    <artifactId>r2dbc-mssql</artifactId>
    <scope>runtime</scope>
</dependency>

Konfigurieren von Spring Boot für die Verwendung von Azure SQL-Datenbank

Ö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:mssql://$AZ_DATABASE_NAME.database.windows.net:1433/demo
spring.r2dbc.username=nonspring@$AZ_DATABASE_NAME
spring.r2dbc.password=$AZ_SQL_SERVER_NON_ADMIN_PASSWORD

Ersetzen Sie die beiden $AZ_DATABASE_NAME-Variablen und die $AZ_SQL_SERVER_NON_ADMIN_PASSWORD-Variable durch die Werte, die Sie zu Beginn dieses Artikels konfiguriert haben.

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:

Screenshot of the running application.

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 INT IDENTITY PRIMARY KEY, description VARCHAR(255), details VARCHAR(4096), done BIT);

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:

Screenshot of the creation of the database table.

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 Azure SQL-Datenbank-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:

Screenshot of the cURL test.

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 SQL-Datenbank verwendet.

Bereinigen von Ressourcen

Um alle während dieser Schnellstartanleitung verwendeten Ressourcen zu sauber, 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).