חיבור JDBC למסד נתונים של ניב GoogleSQL

דף זה מראה לכם כיצד לבצע פעולות בסיסיות ב-Spanner באמצעות מנהל ההתקן של Spanner JDBC.

התקנת מנהל התקן JDBC

בצעו את השלבים בספריות לקוח של Spanner כדי להגדיר אימות, ולאחר מכן הוסיפו את תלויות מנהל ההתקן של Spanner JDBC, המוצגות בקטע הבא, לקובץ ה-pom.xml שלכם.

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>com.google.cloud</groupId>
      <artifactId>libraries-bom</artifactId>
      <version>26.76.0</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

<dependencies>
  <dependency>
    <groupId>com.google.cloud</groupId>
    <artifactId>google-cloud-spanner-jdbc</artifactId>
    <exclusions>
      <exclusion>
        <groupId>com.google.api.grpc</groupId>
        <artifactId>proto-google-cloud-spanner-executor-v1</artifactId>
      </exclusion>
    </exclusions>
  </dependency>
אם אתם משתמשים ב-framework שנדרש בו שם מחלקה ב-Java כדי לטעון את מנהל ההתקן של JDBC, השם הוא com.google.cloud.spanner.jdbc.JdbcDriver. הוראות להגדרת חיבור מופיעות במאמרי העזרה של API בנושא JdbcDriver.

התחברות למסד נתונים ב-Spanner

בתיאור המחלקה JdbcDriver מוצגת התחביר של מחרוזת החיבור, והוא כולל קוד לדוגמה ליצירת חיבור ולהרצת שאילתה.

מנהל ההתקן מזהה אוטומטית את הניב של ה-SQL (GoogleSQL או PostgreSQL) של מסד הנתונים שצוין. פרמטר של ניב לא נדרש ולא מותר.

חיבור לאמולטור

כדי להתחבר לאמולטור, מגדירים את משתנה הסביבה SPANNER_EMULATOR_HOST, לדוגמה:

‫Linux / macOS

export SPANNER_EMULATOR_HOST=localhost:9010

Windows

set SPANNER_EMULATOR_HOST=localhost:9010

פעולה זו מורה לדרייבר Spanner JDBC להתחבר לאמולטור שפועל על localhost במקום לשירות הייצור המוגדר כברירת מחדל.

דוגמאות

דוגמאות הקוד הבאות מכסות כמה מקרי שימוש נפוצים.

הפעל עדכון סכימה

דוגמת הקוד הבאה מוסיפה את הטבלה Singers למסד הנתונים על ידי יצירת חיבור JDBC תחילה ולאחר מכן יצירת הטבלה:

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);
  }

  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]");
  }
}

שימוש בטרנזקציה במצב אישור אוטומטי כדי להוסיף שורות

אם אינך צריך לבצע מספר פעולות כקבוצה, תוכל להשתמש בעסקה במצב commit אוטומטי, שהיא התנהגות ברירת המחדל. בדוגמת הקוד הבאה נעשה שימוש בטרנזקציה במצב אישור אוטומטי כדי להוסיף שורות לטבלה Singers:

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);
  }

  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));
      }
    }
  }
}

שליטה באופן שבו כמה פעולות מתבצעות כקבוצה

אם ברצונך לשלוט אם Spanner מבצע מספר פעולות יחד כקבוצה, תוכל להשבית את מצב ה-autocommit. דוגמת הקוד הבאה משתמשת ב-connection.setAutoCommit(false) וב-connection.commit() כדי להוסיף שורות לטבלת Singers.

import com.google.common.collect.ImmutableList;
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Arrays;

class BatchDmlExample {
  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 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);
  }

  // This example shows how to execute a batch of DML statements with the JDBC driver.
  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);

    ImmutableList<Singer> singers = ImmutableList.of(
        new Singer(10, "Marc", "Richards", BigDecimal.valueOf(10000)),
        new Singer(11, "Amirah", "Finney", BigDecimal.valueOf(195944.10d)),
        new Singer(12, "Reece", "Dunn", BigDecimal.valueOf(10449.90))
    );

    try (Connection connection = DriverManager.getConnection(connectionUrl)) {
      connection.setAutoCommit(false);
      // Use prepared statements for the lowest possible latency when executing the same SQL string
      // multiple times.
      try (PreparedStatement statement = connection.prepareStatement(
          "INSERT INTO Singers (SingerId, FirstName, LastName, Revenues)\n" 
              + "VALUES (?, ?, ?, ?)")) {
        for (Singer singer : singers) {
          statement.setLong(1, singer.singerId);
          statement.setString(2, singer.firstName);
          statement.setString(3, singer.lastName);
          statement.setBigDecimal(4, singer.revenues);
          // Add the current parameter values to the batch.
          statement.addBatch();
        }
        // Execute the batched statements.
        int[] updateCounts = statement.executeBatch();
        connection.commit();
        System.out.printf("Batch insert counts: %s%n", Arrays.toString(updateCounts));
      }
    }
  }
}

הפעלת שאילתת SQL

דוגמת הקוד הבאה מחזירה את כל השורות בטבלת Singers מסודרות לפי שם המשפחה של הזמר:

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);
  }

  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));
        }
      }
    }
  }
}

המאמרים הבאים