Tiefgreifendes Verständnis der Verwendung von r2dbc in MySQL

Tiefgreifendes Verständnis der Verwendung von r2dbc in MySQL

Einführung

MySQL sollte eine sehr häufig verwendete Datenbank sein, die wir in unserer täglichen Arbeit verwenden. Obwohl MySQL jetzt Oracle gehört, ist es Open Source und sein Marktanteil ist immer noch sehr hoch.

Heute stellen wir die Verwendung von r2dbc in MySQL vor.

Maven-Abhängigkeit von r2dbc-mysql

Um r2dbc-mysql zu verwenden, müssen wir die folgenden Maven-Abhängigkeiten hinzufügen:

<Abhängigkeit>
  <groupId>dev.miku</groupId>
  <artifactId>r2dbc-mysql</artifactId>
  <version>0.8.2.RELEASE</version>
</Abhängigkeit>

Wenn Sie die Snapshot-Version verwenden möchten, können Sie natürlich Folgendes tun:

<Abhängigkeit>
  <groupId>dev.miku</groupId>
  <artifactId>r2dbc-mysql</artifactId>
  <version>${r2dbc-mysql.version}.BUILD-SNAPSHOT</version>
</Abhängigkeit>

<Repository>
  <id>Sonatype-Schnappschüsse</id>
  <name>SonaType-Schnappschüsse</name>
  <url>https://oss.sonatype.org/content/repositories/snapshots</url>
  <Schnappschüsse>
    <aktiviert>wahr</aktiviert>
  </Schnappschüsse>
</Repository>

Erstellen einer ConnectionFactory

Der Code zum Erstellen der ConnectionFactory verwendet tatsächlich die Standardschnittstelle von r2dbc und ist daher im Wesentlichen identisch mit dem zuvor erwähnten Erstellungscode von h2:

// Hinweis: Der Query-String muss URL-kodiert sein
VerbindungsFactory VerbindungsFactory = VerbindungsFactories.get(
  "r2dbcs:mysql://root:[email protected]:3306/r2dbc?" +
  "zeroDate=use_round&" +
  "sslMode=Identität_verifizieren&" +
  "useServerPrepareStatement=true&" +
  "tlsVersion=TLSv1.3%2CTLSv1.2%2CTLSv1.1&" +
  "sslCa=%2FPfad%2Fzu%2Fmysql%2Fca.pem&" +
  "sslKey=%2FPfad%2Fzum%2Fmysql%2FClient-Schlüssel.pem&" +
  "sslCert=%2FPfad%2Fzu%2Fmysql%2Fclient-cert.pem&" +
  „sslKeyPassword=Schlüssel-PEM-Passwort-hier-eingeben“
)

// Erstellen eines Mono mit Project Reactor
Mono<Verbindung> connectionMono = Mono.from(connectionFactory.create());

Der Unterschied besteht darin, dass die von ConnectionFactories übergebenen Parameter unterschiedlich sind.

Wir unterstützen auch das Unix-Domain-Socket-Format:

// Minimale Konfiguration für Unix Domain Socket
Verbindungsfabrik Verbindungsfabrik = Verbindungsfabriken.get("r2dbc:mysql://root@unix?unixSocket=%2FPfad%2Fzu%2Fmysql.sock")

Mono<Verbindung> connectionMono = Mono.from(connectionFactory.create());

Ebenso unterstützen wir das Erstellen einer ConnectionFactory aus ConnectionFactoryOptions:

ConnectionFactoryOptions-Optionen = ConnectionFactoryOptions.builder()
  .option(TREIBER, "mysql")
  .option(HOST, "127.0.0.1")
  .option(BENUTZER, "root")
  .option(PORT, 3306) // optional, Standard 3306
  .option(PASSWORD, "Datenbankpasswort hier drin") // optional, Standard null, null bedeutet, dass kein Passwort vorhanden ist
  .option(DATABASE, "r2dbc") // optional, Standard null, null bedeutet, dass die Datenbank nicht angegeben wird
  .option(CONNECT_TIMEOUT, Duration.ofSeconds(3)) // optional, Standard null, null bedeutet kein Timeout
  .option(SSL, true) // optional, der Standard-SSL-Modus ist „preferred“, er wird ignoriert, wenn der SSL-Modus gesetzt ist
  .option(Option.valueOf("sslMode"), "verify_identity") // optional, Standard "bevorzugt"
  .option(Option.valueOf("sslCa"), "/Pfad/zu/mysql/ca.pem") // erforderlich, wenn sslMode „verify_ca“ oder „verify_identity“ ist, Standard null, null bedeutet, dass kein Server-CA-Zertifikat vorhanden ist
  .option(Option.valueOf("sslCert"), "/Pfad/zu/mysql/client-cert.pem") // optional, Standard null, null bedeutet, dass kein Client-Zertifikat vorhanden ist
  .option(Option.valueOf("sslKey"), "/Pfad/zu/mysql/Client-Schlüssel.pem") // optional, Standard null, null bedeutet, dass kein Client-Schlüssel vorhanden ist
  .option(Option.valueOf("sslKeyPassword"), "key-pem-password-in-here") // optional, Standard null, null bedeutet, dass es kein Passwort für den Client-Schlüssel gibt (also "sslKey")
  .option(Option.valueOf("tlsVersion"), "TLSv1.3,TLSv1.2,TLSv1.1") // optional, Standard wird automatisch vom Server ausgewählt
  .option(Option.valueOf("sslHostnameVerifier"), "com.example.demo.MyVerifier") // optional, Standard ist null, null bedeutet, Standard-Verifier zu verwenden
  .option(Option.valueOf("sslContextBuilderCustomizer"), "com.example.demo.MyCustomizer") // optional, Standard ist No-Op-Customizer
  .option(Option.valueOf("zeroDate"), "use_null") // optional, Standard "use_null"
  .option(Option.valueOf("useServerPrepareStatement"), true) // optional, Standardwert: false
  .option(Option.valueOf("tcpKeepAlive"), true) // optional, Standardwert: false
  .option(Option.valueOf("tcpNoDelay"), true) // optional, Standardwert: false
  .option(Option.valueOf("autodetectExtensions"), false) // optional, Standardwert: false
  .bauen();
ConnectionFactory VerbindungsFactory = ConnectionFactories.get(Optionen);

// Erstellen eines Mono mit Project Reactor
Mono<Verbindung> connectionMono = Mono.from(connectionFactory.create());

Oder das folgende Unix-Domain-Socket-Format:

// Minimale Konfiguration für Unix Domain Socket
ConnectionFactoryOptions-Optionen = ConnectionFactoryOptions.builder()
  .option(TREIBER, "mysql")
  .option(Option.valueOf("unixSocket"), "/Pfad/zu/mysql.sock")
  .option(BENUTZER, "root")
  .bauen();
ConnectionFactory VerbindungsFactory = ConnectionFactories.get(Optionen);

Mono<Verbindung> connectionMono = Mono.from(connectionFactory.create());

Erstellen einer Verbindung mit MySqlConnectionFactory

Im obigen Beispiel verwenden wir die allgemeine r2dbc-API, um eine Verbindung herzustellen. In ähnlicher Weise können wir auch die einzigartige MySqlConnectionFactory verwenden, um eine Verbindung herzustellen:

MySqlConnectionConfiguration-Konfiguration = MySqlConnectionConfiguration.builder()
  .host("127.0.0.1")
  .Benutzer("root")
  .port(3306) // optional, Standard 3306
  .password("Datenbankpasswort hier drin") // optional, Standard null, null bedeutet, dass kein Passwort vorhanden ist
  .database("r2dbc") // optional, Standard null, null bedeutet, dass die Datenbank nicht angegeben wurde
  .serverZoneId(ZoneId.of("Continent/City")) // optional, Standard null, null bedeutet, dass die Zeitzone des Servers beim Verbindungsaufbau abgefragt wird
  .connectTimeout(Duration.ofSeconds(3)) // optional, Standard null, null bedeutet kein Timeout
  .sslMode(SslMode.VERIFY_IDENTITY) // optional, Standard SslMode.PREFERRED
  .sslCa("/Pfad/zu/mysql/ca.pem") // erforderlich, wenn sslMode VERIFY_CA oder VERIFY_IDENTITY ist, Standard null, null bedeutet, dass kein Server-CA-Zertifikat vorhanden ist
  .sslCert("/Pfad/zu/mysql/client-cert.pem") // optional, standardmäßig ist kein Client-SSL-Zertifikat vorhanden
  .sslKey("/Pfad/zu/mysql/Client-Schlüssel.pem") // optional, standardmäßig ist kein Client-SSL-Schlüssel vorhanden
  .sslKeyPassword("key-pem-password-in-here") // optional, standardmäßig ist kein Client-SSL-Schlüsselpasswort vorhanden
  .tlsVersion(TlsVersions.TLS1_3, TlsVersions.TLS1_2, TlsVersions.TLS1_1) // optional, Standard wird automatisch vom Server ausgewählt
  .sslHostnameVerifier(MyVerifier.INSTANCE) // optional, Standard ist null, null bedeutet, Standard-Verifier verwenden
  .sslContextBuilderCustomizer(MyCustomizer.INSTANCE) // optional, Standard ist No-Op-Customizer
  .zeroDateOption(ZeroDateOption.USE_NULL) // optional, Standard ZeroDateOption.USE_NULL
  .useServerPrepareStatement() // Benutze servervorbereitende Anweisungen, standardmäßig werden clientvorbereitende Anweisungen verwendet
  .tcpKeepAlive(true) // optional, steuert TCP Keep Alive, Standard ist false
  .tcpNoDelay(true) // optional, steuert TCP No Delay, Standard ist false
  .autodetectExtensions(false) // optional, steuert die automatische Erkennung von Erweiterungen, Standard ist true
  .extendWith(MyExtension.INSTANCE) // optional, eine Erweiterung manuell in Erweiterungen erweitern, standardmäßig mit automatischer Erkennung
  .bauen();
ConnectionFactory connectionFactory = MySqlConnectionFactory.from(Konfiguration);

// Erstellen eines Mono mit Project Reactor
Mono<Verbindung> connectionMono = Mono.from(connectionFactory.create());

Oder die folgende Unix-Domain-Socket-Methode:

// Minimale Konfiguration für Unix Domain Socket
MySqlConnectionConfiguration-Konfiguration = MySqlConnectionConfiguration.builder()
  .unixSocket("/Pfad/zu/mysql.sock")
  .Benutzer("root")
  .bauen();
ConnectionFactory connectionFactory = MySqlConnectionFactory.from(Konfiguration);

Mono<Verbindung> connectionMono = Mono.from(connectionFactory.create());

Execute-Anweisung

Sehen wir uns zunächst eine einfache Anweisung ohne Parameter an:

connection.createStatement("INSERT INTO `person` (`Vorname`, `Nachname`) VALUES ('wer', 'wie')")
  .execute(); // gibt einen Publisher inklusive einem Ergebnis zurück

Schauen Sie sich dann eine Anweisung mit Parametern an:

connection.createStatement("INSERT INTO `person` (`birth`, `nickname`, `show_name`) VALUES (?, ?name, ?name)")
  .bind(0, LocalDateTime.of(2019, 6, 25, 12, 12, 12))
  .bind("name", "Jemand") // Keine Eins-zu-eins-Bindung, rufen Sie native Indexbindungen zweimal auf, bzw. rufen Sie Namensbindungen einmal auf.
  .hinzufügen()
  .bind(0, LocalDateTime.of(2009, 6, 25, 12, 12, 12))
  .bind(1, "Mein Spitzname")
  .bind(2, "Benennung anzeigen")
  .returnGeneratedValues("generierte_ID")
  .execute(); // gibt einen Publisher einschließlich zwei Ergebnissen zurück.

Beachten Sie, dass Sie, wenn der Parameter null ist, bindNull verwenden können, um den Nullwert zu binden.

Als nächstes schauen wir uns einen Batch-Ausführungsvorgang an:

Verbindung.createBatch()
  .add("INSERT INTO `person` (`Vorname`, `Nachname`) VALUES ('wer', 'wie')")
  .add("UPDATE `Erde` SET `Anzahl` = `Anzahl` + 1 WHERE `id` = 'Mensch'")
  .execute(); // gibt einen Publisher einschließlich zwei Ergebnissen zurück.

Durchführung von Transaktionen

Schauen wir uns ein Beispiel für die Ausführung einer Transaktion an:

Verbindung.BeginTransaction()
  .then(Mono.from(connection.createStatement("INSERT INTO `person` (`Vorname`, `Nachname`) VALUES ('wer', 'wie')").execute()))
  .flatMap(Ergebnis::getRowsUpdated)
  .thenMany(connection.createStatement("INSERT INTO `person` (`birth`, `nickname`, `show_name`) VALUES (?, ?name, ?name)")
    .bind(0, LocalDateTime.of(2019, 6, 25, 12, 12, 12))
    .bind("Name", "Jemand")
    .hinzufügen()
    .bind(0, LocalDateTime.of(2009, 6, 25, 12, 12, 12))
    .bind(1, "Mein Spitzname")
    .bind(2, "Benennung anzeigen")
    .returnGeneratedValues("generierte_ID")
    .ausführen())
  .flatMap(Ergebnis::getRowsUpdated)
  .then(Verbindung.commitTransaction());

Threadpool verwenden

Um die Ausführungseffizienz der Datenbank zu verbessern und den Aufwand für das Herstellen von Verbindungen zu verringern, verfügen allgemeine Datenbankverbindungen über das Konzept von Verbindungspools. In ähnlicher Weise verfügt auch r2dbc über einen Verbindungspool namens r2dbc-pool.

r2dbc-pool-Abhängigkeiten:

<Abhängigkeit>
 <groupId>io.r2dbc</groupId>
 <artifactId>r2dbc-pool</artifactId>
 <version>${version}</version>
</Abhängigkeit>

Wenn Sie eine Snapshot-Version verwenden möchten, können Sie diese auch folgendermaßen angeben:

<Abhängigkeit>
 <groupId>io.r2dbc</groupId>
 <artifactId>r2dbc-pool</artifactId>
 <version>${version}.BUILD-SNAPSHOT</version>
</Abhängigkeit>

<Repository>
 <id>Spring-Libs-Schnappschuss</id>
 <name>Spring-Snapshot-Repository</name>
 <url>https://repo.spring.io/libs-snapshot</url>
</Repository>

Sehen wir uns an, wie der Datenbankverbindungspool angegeben wird:

ConnectionFactory connectionFactory = ConnectionFactories.get("r2dbc:pool:<mein-Treiber>://<Host>:<Port>/<Datenbank>[?maxIdleTime=PT60S[&…]");

Herausgeber<? erweitert Verbindung> connectionPublisher = connectionFactory.create();

Wie Sie sehen, müssen wir der Verbindungs-URL nur den Pool-Treiber hinzufügen.

In ähnlicher Weise können wir es auch über ConnectionFactoryOptions erstellen:

VerbindungsFactory VerbindungsFactory = VerbindungsFactories.get(ConnectionFactoryOptions.builder()
  .option(TREIBER, "Pool")
  .option(PROTOCOL, "postgresql") // Treiberkennung, PROTOCOL wird vom Pool als DRIVER delegiert.
  .option(HOST, "…")
  .option(PORT, "…") 
  .option(BENUTZER, "...")
  .option(PASSWORT, "…")
  .option(DATENBANK, "…")
  .bauen());

Herausgeber<? erweitert Verbindung> connectionPublisher = connectionFactory.create();

// Alternative: Erstellen eines Mono mit Project Reactor
Mono<Verbindung> connectionMono = Mono.from(connectionFactory.create());

Schließlich können Sie den Thread-Pool auch direkt verwenden, indem Sie eine ConnectionPoolConfiguration erstellen:

VerbindungsFactory VerbindungsFactory = ...;

ConnectionPoolConfiguration-Konfiguration = ConnectionPoolConfiguration.builder(connectionFactory)
  .maxIdleTime(Dauer.vonMillis(1000))
  .maxSize(20)
  .bauen();

ConnectionPool Pool = neuer ConnectionPool(Konfiguration);
 

Mono<Verbindung> connectionMono = pool.create();

// später

Verbindung Verbindung = …;
Mono<Void> release = connection.close(); // hat die Verbindung wieder zum Pool freigegeben

// Herunterfahren der Anwendung
pool.entsorgen();

Dies ist das Ende dieses Artikels über ein vertieftes Verständnis der Verwendung von r2dbc in MySQL. Weitere relevante MySQL-R2dbc-Inhalte finden Sie in den vorherigen Artikeln von 123WORDPRESS.COM oder in den folgenden verwandten Artikeln. Ich hoffe, dass jeder 123WORDPRESS.COM in Zukunft unterstützen wird!

Das könnte Sie auch interessieren:
  • MySQL-Installationsdiagramm. Grafisches MySQL-Installationstutorial (detaillierte Anweisungen).
  • Verwendungshinweise für die Mysql-String-Interception-Funktion SUBSTRING
  • MySQL-Benutzererstellung und Autorisierungsmethode
  • Detaillierte Verwendung der MySQL-Update-Anweisung
  • Anweisungen zur Verwendung der MySQL CASE WHEN-Anweisung
  • Detaillierte Einführung in die Unterschiede zwischen int, bigint, smallint und tinyint in MySQL
  • mysql Index hinzufügen mysql wie man einen Index erstellt
  • Verwendung von „Replace“ in MySQL

<<:  So legen Sie mit CSS eine Hintergrundunschärfe fest

>>:  Verwenden Sie das Docker-Buildkit, um ein Docker-Image zu erstellen, das auf dem Raspberry Pi verwendet werden kann

Artikel empfehlen

Wichtige Punkte zum Schreiben von Inhalten für META-Tags in HTML-Webseiten

Das META-Tag ist ein Hilfstag im Kopfbereich der ...

Navicat-Remoteverbindung zur MySQL-Implementierungsschritteanalyse

Vorwort Ich glaube, dass jeder auf einem Remote-S...

So funktionieren React Hooks

Inhaltsverzeichnis 1. React Hooks vs. reine Funkt...

Vue.js implementiert Erläuterungen zum Tab-Umschalten und Farbwechseln

Bei der Implementierung dieser Funktion konnte di...

Layout im Vue.js-Stil Allgemeine Fähigkeiten zur Flutter-Geschäftsentwicklung

Korrespondenz zwischen Flutter und CSS im Shadow-...

Beispiele für personalisiertes und kreatives Website-Design (30)

Aus diesem Grund haben wir eine Auswahl von 30 Kom...

Rückblick auf die besten Webdesign-Arbeiten 2012 [Teil 1]

Zum Beginn des neuen Jahres möchte ich meinen Fre...

Einige Dinge, die beim Erstellen einer Webseite zu beachten sind

--Backup der Homepage 1.txt-Text 2. Scannen Sie da...

Problem mit Zeitzonenfehler im Docker-Container

Inhaltsverzeichnis Hintergrund Frage Problemanaly...