Se usó la API de Cloud Translation para traducir esta página.
Switch to English

Usa el controlador JDBC de código abierto

En esta página, se muestra cómo realizar operaciones básicas en Cloud Spanner con el controlador JDBC de código abierto.

Instala el controlador JDBC

Sigue los pasos en Bibliotecas cliente de Cloud Spanner para configurar la autenticación y, luego, agrega las dependencias de controladores JDBC de Cloud Spanner, que se muestran en el siguiente fragmento, a tu archivo pom.xml.

<dependencies>
  <!-- The Spanner JDBC driver dependency -->
  <dependency>
    <groupId>com.google.cloud</groupId>
    <artifactId>google-cloud-spanner-jdbc</artifactId>
  </dependency>

  <!-- Test dependencies -->
  <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13.1</version>
    <scope>test</scope>
  </dependency>
  <dependency>
    <groupId>com.google.truth</groupId>
    <artifactId>truth</artifactId>
    <version>1.1</version>
    <scope>test</scope>
  </dependency>
</dependencies>
En caso de que uses un marco de trabajo que requiera el nombre de clase Java para cargar el controlador JDBC, es com.google.cloud.spanner.jdbc.JdbcDriver. Consulta la documentación de la API para JdbcDriver sobre cómo configurar una conexión.

Conéctate al emulador

Para conectarte al emulator, configura la variable de entorno SPANNER_EMULATOR_HOST, por ejemplo:

Linux/macOS

export SPANNER_EMULATOR_HOST=localhost:9010

Windows

set SPANNER_EMULATOR_HOST=localhost:9010

Esto le indica al controlador JDBC que se conecte al emulador que se ejecuta en el localhost, en lugar del servicio de producción predeterminado.

Ejecuta una actualización de esquema

En el siguiente ejemplo de código, se agrega la tabla Singers a la base de datos mediante la creación de una conexión JDBC y, luego, se crea:

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

Usa una transacción en el modo de confirmación automática para agregar filas

Si no necesitas confirmar varias operaciones como un grupo, puedes usar una transacción en el modo de confirmación automática, que es el comportamiento predeterminado. En el siguiente ejemplo de código, se usa una transacción en el modo de confirmación automática para agregar filas a la tabla Singers:

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

Controla cómo se confirman varias operaciones como un grupo

Si deseas controlar si Cloud Spanner confirma varias operaciones como un grupo, puedes inhabilitar el modo de confirmación automática. En el siguiente ejemplo de código, se usan connection.setAutoCommit(false) y connection.commit() para agregar filas a la tabla Singers.

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

Ejecuta una consulta de SQL

En el siguiente ejemplo de código, se muestran todas las filas de la tabla Singers ordenadas por el apellido del cantante:

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

Declaraciones de administración de sesiones

Además de las declaraciones de consulta de SQL, el controlador JDBC de código abierto (Java Database Connectivity) para Cloud Spanner es compatible con declaraciones de administración de sesiones, que te permiten modificar el estado de tu conexión, ejecutar transacciones y ejecutar lotes de declaraciones de manera eficiente.

Declaraciones de conexión

Las siguientes declaraciones realizan cambios o muestran propiedades de la conexión actual.

SHOW VARIABLE READONLY

Muestra un conjunto de resultados con una fila y una columna de tipo BOOL que indican si la conexión se encuentra en modo de solo lectura o no.

SET READONLY

Sintaxis
SET READONLY = { true | false }

Establece si la conexión está en modo de solo lectura.

Puedes ejecutar esta declaración solo si no hay transacciones activas.

SHOW VARIABLE AUTOCOMMIT

Muestra un conjunto de resultados con una fila y una columna de tipo BOOL que indican si la conexión está en modo AUTOCOMMIT.

SET AUTOCOMMIT

Sintaxis
SET AUTOCOMMIT = { true | false }

Establece el modo AUTOCOMMIT de la conexión.

Puedes ejecutar esta declaración solo si no hay transacciones activas.

SHOW VARIABLE RETRY_ABORTS_INTERNALLY

Muestra un conjunto de resultados con una fila y una columna de tipo BOOL que indican si la conexión reintenta de manera automática las transacciones anuladas.

SET RETRY_ABORTS_INTERNALLY

Sintaxis
SET RETRY_ABORTS_INTERNALLY = { true | false }

Establece si la conexión reintenta de manera automática las transacciones anuladas.

Puedes ejecutar esta declaración solo si no hay transacciones activas.

Cuando habilitas RETRY_ABORTS_INTERNALLY, la conexión mantiene una suma de verificación criptográfica de todos los datos que la conexión muestra a la aplicación cliente y todos los recuentos de actualizaciones que informa la conexión durante la transacción. Si Cloud Spanner anula la transacción, la conexión intenta ejecutar la misma transacción y verifica si los datos devueltos son exactamente iguales a los datos que se muestran en la transacción original. Si los datos coinciden, Cloud Spanner continúa con la transacción. Si los datos no coinciden, la transacción falla y arroja AbortedDueToConcurrentModification.

Esta configuración se habilita de forma predeterminada. Recomendamos desactivar esta configuración si tu aplicación ya reintenta transacciones anuladas.

SHOW VARIABLE AUTOCOMMIT_DML_MODE

Muestra un conjunto de resultados con una fila y una columna de tipo STRING que indican el modo de confirmación automática para las declaraciones de lenguaje de manipulación de datos (DML).

Esta variable tiene efecto solo cuando habilitas el modo AUTOCOMMIT en la conexión.

SET AUTOCOMMIT_DML_MODE

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

Establece el modo de confirmación automática para las declaraciones DML:

  • En el modo TRANSACTIONAL, el controlador ejecuta las declaraciones DML como transacciones atómicas independientes. El controlador crea una nueva transacción, ejecuta la declaración DML y confirma la transacción cuando se ejecuta de manera correcta o revierte la transacción en caso de error.
  • En el modo PARTITIONED_NON_ATOMIC, el controlador ejecuta declaraciones DML como declaraciones de actualización particionadas. Una declaración de actualización particionada puede ejecutarse como una serie de varias transacciones, cada una de las cuales cubre un subconjunto de las filas afectadas, y la declaración particionada que proporciona una semántica debilitada a cambio de mejor escalabilidad y rendimiento.

Puedes ejecutar esta declaración solo si tienes habilitado el modo AUTOCOMMIT.

SHOW VARIABLE STATEMENT_TIMEOUT

Muestra un conjunto de resultados con una fila y una columna de tipo STRING que indican el valor de tiempo de espera actual para las declaraciones. El valor es un número entero seguido de un sufijo que indica la unidad de tiempo. Un valor de NULL indica que no hay ningún valor de tiempo de espera establecido. Si se estableció un valor de tiempo de espera de la declaración, las declaraciones que tarden más que el valor de tiempo de espera especificado provocarán un java.sql.SQLTimeoutException y, luego, invalidarán la transacción.

SET STATEMENT_TIMEOUT

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

Establece el valor de tiempo de espera de la declaración para todas las declaraciones posteriores en la conexión. Si se establece el valor de tiempo de espera como NULL, se inhabilitan los tiempos de espera de las declaraciones para la conexión.

Las unidades de tiempo admitidas son las que se muestran a continuación:

  • s: Segundos
  • ms: Milésimas de segundo
  • us: Microsegundos
  • ns: Nanosegundos

Si se agota el tiempo de espera de una declaración durante una transacción, se invalida la transacción, todas las declaraciones posteriores de la transacción invalidada (excepto ROLLBACK) fallan y el controlador JDBC arroja java.sql.SQLTimeoutException.

SHOW VARIABLE READ_ONLY_STALENESS

Muestra un conjunto de resultados con una fila y una columna de tipo STRING que indican la configuración de inactividad de solo lectura actual que Cloud Spanner usa para las consultas y transacciones de solo lectura en el modo AUTOCOMMIT. La configuración predeterminada es STRONG.

SET READ_ONLY_STALENESS

Sintaxis
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 }' }

Establece la configuración de inactividad de solo lectura para todas las transacciones posteriores de solo lectura que no estén en el modo AUTOCOMMIT y para todas las consultas en el modo AUTOCOMMIT.

Las opciones de límite de marca de tiempo son las que se muestran a continuación:

Las marcas de tiempo deben usar el siguiente formato:

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

Las unidades de tiempo admitidas para configurar los valores MAX_STALENESS y EXACT_STALENESS son:

  • s: Segundos
  • ms: Milésimas de segundo
  • us: Microsegundos
  • ns: Nanosegundos

Puedes ejecutar esta declaración solo si no hay transacciones activas.

Declaraciones de transacciones

Las siguientes declaraciones administran y confirman transacciones de Cloud Spanner.

SHOW VARIABLE READ_TIMESTAMP

Muestra un conjunto de resultados con una fila y una columna de tipo TIMESTAMP que contienen la marca de tiempo de lectura de la transacción de solo lectura más reciente. Esta declaración muestra una marca de tiempo solo cuando una transacción de solo lectura aún está activa y ejecuta al menos una consulta, o inmediatamente después de que se confirma una transacción de solo lectura y antes de que comience una nueva transacción. De lo contrario, el resultado es NULL.

SHOW VARIABLE COMMIT_TIMESTAMP

Muestra un conjunto de resultados con una fila y una columna de tipo TIMESTAMP que contienen la marca de tiempo de confirmación de la última transacción de lectura y escritura que confirmó Cloud Spanner. Esta declaración muestra una marca de tiempo solo cuando la ejecutas después de confirmar una transacción de lectura y escritura, y antes de ejecutar cualquier declaración SELECT, DML o de cambio de esquema posterior. De lo contrario, el resultado es NULL.

BEGIN [TRANSACTION]

Inicia una transacción nueva.

  • Si habilitaste el modo AUTOCOMMIT, esta declaración quitará la conexión del modo AUTOCOMMIT de forma temporal. La conexión regresa al modo AUTOCOMMIT cuando finaliza la transacción.
  • Si inhabilitaste el modo AUTOCOMMIT, esta declaración es opcional y no tiene ningún efecto.

Puedes ejecutar esta declaración solo si no hay transacciones activas.

COMMIT [TRANSACTION]

Confirma la transacción actual.

  • Si se confirma una transacción de lectura y escritura, todas las actualizaciones de esta transacción serán visibles para otras transacciones y se liberarán todos los bloqueos de la transacción en Cloud Spanner.
  • La confirmación de una transacción de solo lectura finaliza la transacción de solo lectura actual. Cualquier declaración posterior inicia una nueva transacción. No hay diferencia semántica entre COMMIT y ROLLBACK para una transacción de solo lectura.

Puedes ejecutar esta declaración solo mientras haya una transacción activa.

ROLLBACK [TRANSACTION]

Realiza una ROLLBACK de la transacción actual.

  • Si realizas una ROLLBACK de una transacción de lectura y escritura, borras las mutaciones de búfer, reviertes la transacción en Cloud Spanner y liberas todos los bloqueos que tenía la transacción.
  • Si realizas una ROLLBACK de una transacción de solo lectura, finalizas la transacción de solo lectura actual. Las declaraciones posteriores inician una nueva transacción. No hay diferencia semántica entre COMMIT y ROLLBACK para una transacción de solo lectura en una conexión.

Puedes ejecutar esta declaración solo mientras haya una transacción activa.

SET TRANSACTION

Sintaxis
SET TRANSACTION { READ ONLY | READ WRITE }

Establece el modo de transacción para la transacción actual.

Puedes ejecutar esta declaración solo cuando no habilitas el modo AUTOCOMMIT o si iniciaste una transacción temporal con la ejecución de BEGIN [TRANSACTION] y aún no ejecutaste ninguna declaración en la transacción.

Declaraciones por lotes

Las siguientes declaraciones administran lotes de declaraciones de DDL y envían esos lotes a Cloud Spanner.

START BATCH DDL

Inicia un lote de declaraciones de DDL en la conexión. Todas las declaraciones posteriores durante el lote deben ser declaraciones de DDL. Las declaraciones de DDL se almacenan en búfer de manera local y se envían a Cloud Spanner como un solo lote cuando ejecutas RUN BATCH. Ejecutar varias declaraciones de DDL como un lote suele ser más rápido que ejecutar las declaraciones por separado.

Puedes ejecutar esta declaración solo si no hay transacciones activas.

RUN BATCH

Envía todas las declaraciones de DDL almacenadas en búfer en el lote DDL actual a la base de datos, espera a que Cloud Spanner ejecute estas declaraciones y finaliza el lote DDL actual.

Si Cloud Spanner no puede ejecutar al menos una declaración de DDL, RUN BATCH muestra un error para la primera declaración de DDL que Cloud Spanner no puede ejecutar. De lo contrario, RUN BATCH se muestra de forma correcta.

ABORT BATCH

Borra todas las declaraciones de DDL almacenadas en búfer en el lote de DDL actual y finaliza el lote.

Puedes ejecutar esta declaración solo cuando un lote de DDL está activo. Puedes usar ABORT BATCH sin importar si el lote tiene o no declaraciones de DDL almacenadas en búfer.

COMIENZA EL BATCH

Las siguientes declaraciones agrupan las dos declaraciones DML juntas y las envían en una llamada al servidor. Un lote DML se puede ejecutar como parte de una transacción o en modo de confirmación automática.

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

¿Qué sigue?

Obtén respuestas a las preguntas frecuentes sobre el controlador JDBC de código abierto.