Open-Source-JDBC-Treiber verwenden

Auf dieser Seite erfahren Sie, wie Sie grundlegende Vorgänge in Cloud Spanner mithilfe des Open-Source-JDBC-Treibers ausführen.

JDBC-Treiber installieren

Führen Sie die Schritte unter Cloud Spanner-Clientbibliotheken aus, um die Authentifizierung einzurichten, und fügen Sie dann die JDBC-Treiberabhängigkeiten von Cloud Spanner, die im folgenden Snippet angezeigt werden, zur Datei pom.xml hinzu.

<dependencies>
  <!-- The Spanner JDBC driver dependency -->
  <dependency>
    <groupId>com.google.cloud</groupId>
    <artifactId>google-cloud-spanner-jdbc</artifactId>
  </dependency>
  <!--CSV parsing dependencies -->
  <dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-csv</artifactId>
    <version>1.9.0</version>
  </dependency>
  <dependency>
    <groupId>commons-cli</groupId>
    <artifactId>commons-cli</artifactId>
    <version>1.4</version>
  </dependency>

  <!-- Test dependencies -->
  <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13.2</version>
    <scope>test</scope>
  </dependency>
  <dependency>
    <groupId>com.google.truth</groupId>
    <artifactId>truth</artifactId>
    <version>1.1.3</version>
    <scope>test</scope>
  </dependency>
</dependencies>
Wenn Sie ein Framework verwenden, das den Java-Klassennamen zum Laden des JDBC-Treibers benötigt, ist es com.google.cloud.spanner.jdbc.JdbcDriver. Informationen zum Einrichten einer Verbindung finden Sie in der API-Dokumentation für JdbcDriver.

Verbindung zum Emulator herstellen

Um eine Verbindung zum Emulator herzustellen, legen Sie die Umgebungsvariable SPANNER_EMULATOR_HOST fest. Beispiel:

Linux/macOS

export SPANNER_EMULATOR_HOST=localhost:9010

Windows

set SPANNER_EMULATOR_HOST=localhost:9010

Damit wird der JDBC-Treiber angewiesen, eine Verbindung zum Emulator herzustellen, der in localhost ausgeführt wird, statt dem Standard-Produktionsdienst.

Schemaaktualisierung ausführen

Im folgenden Codebeispiel wird die Tabelle Singers der Datenbank hinzugefügt. Dazu wird zuerst eine JDBC-Verbindung und dann die Tabelle erstellt:

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;

class CreateTableExample {

  static void createTable() throws SQLException {
    // TODO(developer): Replace these variables before running the sample.
    String projectId = "my-project";
    String instanceId = "my-instance";
    String databaseId = "my-database";
    createTable(projectId, instanceId, databaseId);
  }

  @SuppressFBWarnings(
      value = "OBL_UNSATISFIED_OBLIGATION",
      justification = "https://github.com/spotbugs/spotbugs/issues/293")
  static void createTable(String projectId, String instanceId, String databaseId)
      throws SQLException {
    String connectionUrl =
        String.format(
            "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s",
            projectId, instanceId, databaseId);
    try (Connection connection = DriverManager.getConnection(connectionUrl)) {
      try (Statement statement = connection.createStatement()) {
        statement.execute(
            "CREATE TABLE Singers (\n"
                + "  SingerId   INT64 NOT NULL,\n"
                + "  FirstName  STRING(1024),\n"
                + "  LastName   STRING(1024),\n"
                + "  SingerInfo BYTES(MAX),\n"
                + "  Revenues   NUMERIC,\n"
                + ") PRIMARY KEY (SingerId)\n");
      }
    }
    System.out.println("Created table [Singers]");
  }
}

Zeilen mit einer Transaktion im automatischen Commit-Modus hinzuzufügen

Wenn Sie nicht mehrere Vorgänge als Gruppe ausführen müssen, können Sie eine Transaktion im Autocommit-Modus verwenden. Dies ist das Standardverhalten. Im folgenden Codebeispiel wird eine Transaktion im Autocommit-Modus verwendet, um der Tabelle Singers Zeilen hinzuzufügen:

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Types;
import java.util.Arrays;
import java.util.List;

class InsertDataExample {
  // Class to contain singer sample data.
  static class Singer {
    final long singerId;
    final String firstName;
    final String lastName;
    final BigDecimal revenues;

    Singer(long singerId, String firstName, String lastName, BigDecimal revenues) {
      this.singerId = singerId;
      this.firstName = firstName;
      this.lastName = lastName;
      this.revenues = revenues;
    }
  }

  static final List<Singer> SINGERS =
      Arrays.asList(
          new Singer(10, "Marc", "Richards", new BigDecimal("104100.00")),
          new Singer(20, "Catalina", "Smith", new BigDecimal("9880.99")),
          new Singer(30, "Alice", "Trentor", new BigDecimal("300183")),
          new Singer(40, "Lea", "Martin", new BigDecimal("20118.12")),
          new Singer(50, "David", "Lomond", new BigDecimal("311399.26")));

  static void insertData() throws SQLException {
    // TODO(developer): Replace these variables before running the sample.
    String projectId = "my-project";
    String instanceId = "my-instance";
    String databaseId = "my-database";
    insertData(projectId, instanceId, databaseId);
  }

  @SuppressFBWarnings(
      value = "OBL_UNSATISFIED_OBLIGATION",
      justification = "https://github.com/spotbugs/spotbugs/issues/293")
  static void insertData(String projectId, String instanceId, String databaseId)
      throws SQLException {
    String connectionUrl =
        String.format(
            "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s",
            projectId, instanceId, databaseId);
    try (Connection connection = DriverManager.getConnection(connectionUrl)) {
      try (PreparedStatement ps =
          connection.prepareStatement(
              "INSERT INTO Singers\n"
                  + "(SingerId, FirstName, LastName, SingerInfo, Revenues)\n"
                  + "VALUES\n"
                  + "(?, ?, ?, ?, ?)")) {
        for (Singer singer : SINGERS) {
          ps.setLong(1, singer.singerId);
          ps.setString(2, singer.firstName);
          ps.setString(3, singer.lastName);
          ps.setNull(4, Types.BINARY);
          ps.setBigDecimal(5, singer.revenues);
          ps.addBatch();
        }
        int[] updateCounts = ps.executeBatch();
        System.out.printf("Insert counts: %s%n", Arrays.toString(updateCounts));
      }
    }
  }
}

Steuern, wie mehrere Vorgänge als Gruppe durchgeführt werden

Wenn Sie steuern möchten, ob Cloud Spanner beim Durchführen eines Commits mehrere Vorgänge als Gruppe zusammenfasst, können Sie den Autocommit-Modus deaktivieren. Im folgenden Codebeispiel werden connection.setAutoCommit(false) und connection.commit() zum Hinzufügen von Zeilen zur Tabelle Singers verwendet.

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Arrays;

class BatchDmlExample {

  static void batchDml() throws SQLException {
    // TODO(developer): Replace these variables before running the sample.
    String projectId = "my-project";
    String instanceId = "my-instance";
    String databaseId = "my-database";
    batchDml(projectId, instanceId, databaseId);
  }

  @SuppressFBWarnings(
      value = "OBL_UNSATISFIED_OBLIGATION",
      justification = "https://github.com/spotbugs/spotbugs/issues/293")
  static void batchDml(String projectId, String instanceId, String databaseId) throws SQLException {
    String connectionUrl =
        String.format(
            "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s",
            projectId, instanceId, databaseId);
    try (Connection connection = DriverManager.getConnection(connectionUrl)) {
      connection.setAutoCommit(false);
      try (Statement statement = connection.createStatement()) {
        statement.addBatch(
            "INSERT INTO Singers (SingerId, FirstName, LastName, Revenues)\n"
                + "VALUES (10, 'Marc', 'Richards', 100000)");
        statement.addBatch(
            "INSERT INTO Singers (SingerId, FirstName, LastName, Revenues)\n"
                + "VALUES (11, 'Amirah', 'Finney', 195944.10)");
        statement.addBatch(
            "INSERT INTO Singers (SingerId, FirstName, LastName, Revenues)\n"
                + "VALUES (12, 'Reece', 'Dunn', 10449.90)");
        int[] updateCounts = statement.executeBatch();
        connection.commit();
        System.out.printf("Batch insert counts: %s%n", Arrays.toString(updateCounts));
      }
    }
  }
}

SQL-Abfrage ausführen

Im folgenden Codebeispiel werden alle Zeilen in der Tabelle Singers zurückgegeben, sortiert nach dem Nachnamen des Sängers:

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class SingleUseReadOnlyExample {

  static void singleUseReadOnly() throws SQLException {
    // TODO(developer): Replace these variables before running the sample.
    String projectId = "my-project";
    String instanceId = "my-instance";
    String databaseId = "my-database";
    singleUseReadOnly(projectId, instanceId, databaseId);
  }

  @SuppressFBWarnings(
      value = "OBL_UNSATISFIED_OBLIGATION",
      justification = "https://github.com/spotbugs/spotbugs/issues/293")
  static void singleUseReadOnly(String projectId, String instanceId, String databaseId)
      throws SQLException {
    String connectionUrl =
        String.format(
            "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s",
            projectId, instanceId, databaseId);
    try (Connection connection = DriverManager.getConnection(connectionUrl);
        Statement statement = connection.createStatement()) {
      // When the connection is in autocommit mode, any query that is executed will automatically
      // be executed using a single-use read-only transaction, even if the connection itself is in
      // read/write mode.
      try (ResultSet rs =
          statement.executeQuery(
              "SELECT SingerId, FirstName, LastName, Revenues FROM Singers ORDER BY LastName")) {
        while (rs.next()) {
          System.out.printf(
              "%d %s %s %s%n",
              rs.getLong(1), rs.getString(2), rs.getString(3), rs.getBigDecimal(4));
        }
      }
    }
  }
}

Anweisungen zur Sitzungsverwaltung

Neben SQL-Abfrageanweisungen unterstützt der Open-Source-JDBC-Treiber (Java Database Connectivity) für Cloud Spanner auch Anweisungen zur Sitzungsverwaltung, mit denen Sie den Status Ihrer Verbindung ändern sowie Transaktionen und Batches von Anweisungen effizient ausführen können.

Verbindungsanweisungen

Mit den folgenden Anweisungen werden die Eigenschaften der aktuellen Verbindung geändert oder aufgerufen.

SHOW VARIABLE READONLY

Gibt eine Ergebnismenge mit einer Zeile und einer Spalte vom Typ BOOL zurück, die anzeigt, ob sich die Verbindung momentan im Lesemodus befindet.

SET READONLY

Syntax
SET READONLY = { true | false }

Legt fest, ob die Verbindung sich im Lesemodus befindet.

Sie können diese Anweisung nur ausführen, wenn keine aktive Transaktion vorhanden ist.

SHOW VARIABLE AUTOCOMMIT

Gibt eine Ergebnismenge mit einer Zeile und einer Spalte vom Typ BOOL zurück, die anzeigt, ob sich die Verbindung im AUTOCOMMIT-Modus befindet.

SET AUTOCOMMIT

Syntax
SET AUTOCOMMIT = { true | false }

Legt den AUTOCOMMIT-Modus der Verbindung fest.

Sie können diese Anweisung nur ausführen, wenn keine aktive Transaktion vorhanden ist.

SHOW VARIABLE RETRY_ABORTS_INTERNALLY

Gibt eine Ergebnismenge mit einer Zeile und einer Spalte vom Typ BOOL zurück, die anzeigt, ob die Verbindung abgebrochene Transaktionen automatisch wiederholt.

SET RETRY_ABORTS_INTERNALLY

Syntax
SET RETRY_ABORTS_INTERNALLY = { true | false }

Legt fest, ob die Verbindung abgebrochene Transaktionen automatisch wiederholen soll.

Sie können diese Anweisung nur ausführen, wenn keine aktive Transaktion vorhanden ist.

Wenn Sie RETRY_ABORTS_INTERNALLY aktivieren, speichert die Verbindung eine kryptografische Prüfsumme aller Daten, die die Verbindung an die Client-Anwendung zurückgibt, und die Gesamtanzahl von Aktualisierungen, die die Verbindung während der Transaktion meldet. Wenn Cloud Spanner die Transaktion abbricht, versucht die Verbindung, dieselbe Transaktion auszuführen und überprüft, ob die zurückgegebenen Daten exakt mit den Daten übereinstimmen, die in der ursprünglichen Transaktion zurückgegeben wurden. Wenn die Daten übereinstimmen, setzt Cloud Spanner die Transaktion fort. Wenn die Daten nicht übereinstimmen, schlägt die Transaktion fehl und es wird AbortedDueToConcurrentModification ausgelöst.

Diese Einstellung ist standardmäßig aktiviert. Wir empfehlen, diese Einstellung zu deaktivieren, wenn Ihre Anwendung bereits abgebrochene Transaktionen wiederholt.

SHOW VARIABLE AUTOCOMMIT_DML_MODE

Gibt eine Ergebnismenge mit einer Zeile und einer Spalte vom Typ STRING zurück, die den Autocommit-Modus für Anweisungen in der Datenbearbeitungssprache (Data-Manipulation Language, DML) anzeigt.

Diese Variable wirkt sich nur dann aus, wenn Sie den AUTOCOMMIT-Modus auf der Verbindung aktivieren.

SET AUTOCOMMIT_DML_MODE

Syntax
SET AUTOCOMMIT_DML_MODE = { 'TRANSACTIONAL' | 'PARTITIONED_NON_ATOMIC' }

Legt den Autocommit-Modus für DML-Anweisungen fest:

  • Im TRANSACTIONAL-Modus führt der Treiber DML-Anweisungen als separate atomare Transaktionen aus. Der Treiber erstellt eine neue Transaktion, führt die DML-Anweisung aus und lässt danach entweder bei erfolgreicher Ausführung ein Commit oder im Falle eines Fehlers ein Rollback der Transaktion durchführen.
  • Im PARTITIONED_NON_ATOMIC-Modus führt der Treiber DML-Anweisungen als partitionierte Aktualisierungsanweisungen aus. Eine partitionierte Aktualisierungsanweisung kann als eine Reihe von mehreren Transaktionen ausgeführt werden, wobei jede davon eine Teilmenge der betroffenen Zeilen abdeckt und die partitionierte Anweisung eine schwache Semantik im Austausch für bessere Skalierbarkeit und Leistung liefert.

Sie können diese Anweisung nur ausführen, wenn Sie den AUTOCOMMIT-Modus aktiviert haben.

SHOW VARIABLE STATEMENT_TIMEOUT

Gibt eine Ergebnismenge mit einer Zeile und einer Spalte vom Typ STRING zurück, die den aktuellen Zeitüberschreitungswert für Anweisungen anzeigt. Der Wert ist eine ganze Zahl, gefolgt von einem Suffix, das die Zeiteinheit angibt. Der Wert von NULL gibt an, dass kein Zeitüberschreitungswert festgelegt ist. Wenn ein Zeitüberschreitungswert festgelegt wurde, verursachen Anweisungen, die länger als das angegebene Zeitlimit dauern, ein java.sql.SQLTimeoutException und machen die Transaktion ungültig.

SET STATEMENT_TIMEOUT

Syntax
SET STATEMENT_TIMEOUT = { '<INT64>{ s | ms | us | ns }' | NULL }

Legt den Zeitüberschreitungswert für alle nachfolgenden Anweisungen auf der Verbindung fest. Wenn Sie den Zeitüberschreitungswert auf NULL festlegen, werden Zeitüberschreitungen von Anweisungen für die Verbindung deaktiviert.

Folgende Zeiteinheiten werden unterstützt:

  • s: Sekunden
  • ms: Millisekunden
  • us: Mikrosekunden
  • ns: Nanosekunden

Die Zeitüberschreitung einer Anweisung während einer Transaktion macht die Transaktion ungültig, alle nachfolgenden Anweisungen in der ungültigen Transaktion (außer ROLLBACK) schlagen fehl und der JDBC-Treiber löst eine java.sql.SQLTimeoutException aus.

SHOW VARIABLE READ_ONLY_STALENESS

Gibt eine Ergebnismenge mit einer Zeile und einer Spalte vom Typ STRING zurück, die die aktuelle Veralterungs-Leseeinstellung anzeigt, die Cloud Spanner für schreibgeschützte Transaktionen und Abfragen im AUTOCOMMIT-Modus verwendet. Die Standardeinstellung ist STRONG.

SET READ_ONLY_STALENESS

Syntax
SET READ_ONLY_STALENESS = { 'STRONG' | 'MIN_READ_TIMESTAMP <timestamp>' | 'READ_TIMESTAMP <timestamp>' |
    'MAX_STALENESS <INT64>{ s | ms | us | ns }' | 'EXACT_STALENESS <INT64>{ s | ms | us | ns }' }

Legt die Veralterungs-Leseeinstellung fest, für alle nachfolgenden schreibgeschützten Transaktionen, die nicht im AUTOCOMMIT-Modus ausgeführt werden, und für alle Abfragen, die in AUTOCOMMIT-Modus.

Die Optionen für Zeitstempelgrenzen sind folgende:

Zeitstempel müssen das folgende Format haben:

YYYY-[M]M-[D]DT[[H]H:[M]M:[S]S[.DDDDDD]][timezone]

Folgende Zeiteinheiten werden zum Festlegen der Werte MAX_STALENESS und EXACT_STALENESS unterstützt:

  • s: Sekunden
  • ms: Millisekunden
  • us: Mikrosekunden
  • ns: Nanosekunden

Sie können diese Anweisung nur ausführen, wenn keine aktive Transaktion vorhanden ist.

Transaktionsanweisungen

Die folgenden Anweisungen verwalten Cloud Spanner-Transaktionen und führen für sie ein Commit durch.

SHOW VARIABLE READ_TIMESTAMP

Gibt eine Ergebnismenge mit einer Zeile und einer Spalte vom Typ TIMESTAMP zurück, die den Lesezeitstempel der letzten schreibgeschützten Transaktion enthält. Diese Anweisung gibt nur dann einen Zeitstempel zurück, wenn entweder eine schreibgeschützte Transaktion noch aktiv ist und mindestens eine Abfrage ausgeführt hat, oder unmittelbar nachdem ein Commit einer schreibgeschützten Transaktion durchgeführt und bevor eine neue Transaktion begonnen wurde. Andernfalls lautet das Ergebnis NULL.

SHOW VARIABLE COMMIT_TIMESTAMP

Gibt eine Ergebnismenge mit einer Zeile und einer Spalte vom Typ TIMESTAMP zurück, die den Commit-Zeitstempel der letzten Lese-/Schreibtransaktion enthält, für die Cloud Spanner ein Commit durchgeführt hat. Diese Anweisung gibt nur dann einen Zeitstempel zurück, wenn Sie sie ausführen, nachdem Sie ein Commit einer Lese-/Schreibtransaktion durchgeführt haben und bevor Sie nachfolgende SELECT-, DML- oder Schemaänderungs-Anweisungen ausführen. Andernfalls lautet das Ergebnis NULL.

BEGIN [TRANSACTION]

Startet eine neue Transaktion.

  • Wenn Sie den AUTOCOMMIT-Modus aktiviert haben, entfernt diese Anweisung vorübergehend die Verbindung aus dem AUTOCOMMIT-Modus. Die Verbindung kehrt in den AUTOCOMMIT-Modus zurück, wenn die Transaktion endet.
  • Wenn Sie den AUTOCOMMIT-Modus deaktiviert haben, ist diese Anweisung optional und hat keine Auswirkungen.

Sie können diese Anweisung nur ausführen, wenn keine aktive Transaktion vorhanden ist.

COMMIT [TRANSACTION]

Führt ein Commit der aktuellen Transaktion durch.

  • Durch das Commit einer Lese-/Schreibtransaktion werden alle Aktualisierungen dieser Transaktion für andere Transaktionen sichtbar und alle Sperren der Transaktion in Cloud Spanner werden aufgehoben.
  • Durch das Commit einer schreibgeschützten Transaktion wird die aktuelle schreibgeschützte Transaktion beendet. Jede nachfolgende Anweisung startet eine neue Transaktion. Es gibt keinen semantischen Unterschied zwischen COMMIT und ROLLBACK für eine schreibgeschützte Transaktion.

Sie können diese Anweisung nur ausführen, während eine aktive Transaktion vorhanden ist.

ROLLBACK [TRANSACTION]

Führt ein ROLLBACK der aktuellen Transaktion durch.

  • Ein ROLLBACK einer Lese-/Schreibtransaktion löscht alle gepufferten Mutationen, führt ein Rollback der Transaktion in Cloud Spanner durch und hebt alle Sperren der Transaktion auf.
  • Ein ROLLBACK einer schreibgeschützten Transaktion beendet die aktuelle schreibgeschützte Transaktion. Jede nachfolgende Anweisung startet eine neue Transaktion. Es gibt keinen semantischen Unterschied zwischen COMMIT und ROLLBACK für eine schreibgeschützte Transaktion auf einer Verbindung.

Sie können diese Anweisung nur ausführen, während eine aktive Transaktion vorhanden ist.

SET TRANSACTION

Syntax
SET TRANSACTION { READ ONLY | READ WRITE }

Legt den Transaktionsmodus für die aktuelle Transaktion fest.

Sie können diese Anweisung nur ausführen, wenn Sie den AUTOCOMMIT-Modus nicht aktivieren oder wenn Sie eine temporäre Transaktion durch Ausführung von BEGIN [TRANSACTION] gestartet und noch keinerlei Anweisungen in der Transaktion ausgeführt haben.

Batch-Anweisungen

Die folgenden Anweisungen verwalten Batches von DDL-Anweisungen und senden sie an Cloud Spanner.

START BATCH DDL

Startet einen Batch von DDL-Anweisungen auf der Verbindung. Alle nachfolgenden Anweisungen im Batch müssen DDL-Anweisungen sein. Die DDL-Anweisungen werden lokal gepuffert und als ein Batch an Cloud Spanner gesendet, wenn Sie RUN BATCH ausführen. Die Ausführung mehrerer DDL-Anweisungen in einem Batch ist in der Regel schneller als die separate Ausführung der Anweisungen.

Sie können diese Anweisung nur ausführen, wenn keine aktive Transaktion vorhanden ist.

RUN BATCH

Sendet alle gepufferten DDL-Anweisungen im aktuellen DDL-Batch an die Datenbank, wartet auf die Ausführung dieser Anweisungen durch Cloud Spanner und beendet den aktuellen DDL-Batch.

Wenn Cloud Spanner nicht mindestens eine DDL-Anweisung ausführen kann, gibt RUN BATCH einen Fehler für die erste DDL-Anweisung zurück, die von Cloud Spanner nicht ausgeführt werden kann. Andernfalls wird RUN BATCH erfolgreich zurückgegeben.

ABORT BATCH

Löscht alle gepufferten DDL-Anweisungen im aktuellen DDL-Batch und beendet den Batch.

Sie können diese Anweisung nur ausführen, wenn ein DDL-Batch aktiv ist. Sie können ABORT BATCH verwenden, unabhängig davon, ob im Batch gepufferte DDL-Anweisungen vorhanden sind oder nicht.

BATCH-DML STARTEN

Mit den folgenden Anweisungen werden die beiden DML-Anweisungen zusammengefasst und in einem Aufruf an den Server gesendet. Ein DML-Batch kann als Teil einer Transaktion oder im Autocommit-Modus ausgeführt werden.

START BATCH DML
INSERT INTO MYTABLE (ID, NAME) VALUES (1, 'ONE')
INSERT INTO MYTABLE (ID, NAME) VALUES (2, 'TWO')
RUN BATCH

Nächste Schritte

Antworten auf häufig gestellte Fragen zum Open-Source-JDBC-Treiber