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 la página sobre bibliotecas cliente de Cloud Spanner para configurar la autenticación y, luego, agrega la dependencia com.google.cloud.google-cloud-spanner-jdbc al archivo de configuración de compilación para tu aplicación. Por ejemplo, si usas Maven, establece el groupId de la dependencia en com.google.cloud y el artifactId en google-cloud-spanner-jdbc.

Ejecuta una actualización de esquema

En el siguiente ejemplo de código, se agrega la tabla Musicians a la base de datos.

Primero, crea una conexión JDBC:

static String getJdbcConnectionUrl(String projectId, String instance,
        String database) {
      String jdbcUrlFormat =
          "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s;credentials=%s";
      String credentialsUrl = "path/to/service-account/credentials/file.json";
      // ...
      String url = String.format(
          jdbcUrlFormat, projectId, instance, database, credentialsUrl);
      return url;
    }

Luego, crea la tabla Musicians:

static void createTableWithJdbc(String projectId, String instance,
        String database) throws SQLException {
      String jdbcUrl = getJdbcConnectionUrl(projectId, instance, database);
      try (Connection connection = DriverManager.getConnection(jdbcUrl)) {
        // Create a test table in a DDL BATCH.
        connection.setAutoCommit(false);
        java.sql.Statement statement = connection.createStatement();
        statement.execute("START BATCH DDL");
        statement.execute(
            "CREATE TABLE Musicians ("
                + "  MusicianId  INT64 NOT NULL,"
                + "  FirstName  STRING(1024),"
                + "  LastName   STRING(1024),"
                + "  MusicianInfo BYTES(MAX)"
                + ") PRIMARY KEY (MusicianId)");
        statement.execute("RUN BATCH");
        connection.commit();
      } catch (SQLException e) {
        if (e.getErrorCode() == Code.ABORTED.value()) {
          // Transaction aborted, retry.
        } else {
          throw e;
        }
      }
      System.out.println("Created table [Musicians].\n");
    }

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

Si no necesitas confirmar varias operaciones como un grupo, puedes usar una transacción en el modo de confirmación automática. El modo de confirmación automática requiere menos código que una transacción por lotes. En el siguiente ejemplo de código, se usa una transacción en el modo de confirmación automática para agregar y borrar filas de la tabla Singers:

static void insertAndDeleteWithJdbc(String projectId, String instance,
        String database) throws SQLException {
      long rowCountInserted = 0;
      long rowCountDeleted = 0;
      String jdbcUrl = getJdbcConnectionUrl(projectId, instance, database);
      try (Connection connection = DriverManager.getConnection(jdbcUrl)) {
        while (true) {
          try {
            try (PreparedStatement ps = connection.prepareStatement(
              "INSERT INTO Singers (SingerId, FirstName, LastName) "
                + "VALUES (?, ?, ?)")) {
              ps.setLong(1, 16);
              ps.setString(2, "Test");
              ps.setString(3, "Singer 16");
              rowCountInserted = ps.executeUpdate();
            }
            try (PreparedStatement ps = connection.prepareStatement(
              "DELETE FROM Singers WHERE Lastname = ?")) {
              ps.setString(1, "Lomond");
              rowCountDeleted = ps.executeUpdate();
            }
            break;
          } catch (SQLException e) {
            if (e.getErrorCode() == Code.ABORTED.value()) {
              // Transaction aborted, retry.
            } else {
              throw e;
            }
          }
        }
      }
      System.out.printf("%d record inserted.\n", rowCountInserted);
      System.out.printf("%d record deleted.\n", rowCountDeleted);
    }

Usar una transacción por lotes para agregar y borrar filas

Si quieres controlar si Cloud Spanner confirma varias operaciones como un grupo, puedes usar una transacción por lotes. En el siguiente ejemplo de código, se usan connection.setAutoCommit(false) y connection.commit() para agregar y borrar filas de la tabla Singers.

static void batchTransactionWithJdbc(String projectId, String instance,
        String database) throws SQLException {
      long rowCountInserted = 0;
      long rowCountDeleted = 0;
      String jdbcUrl = getJdbcConnectionUrl(projectId, instance, database);
      try (Connection connection = DriverManager.getConnection(jdbcUrl)) {
        while (true) {
          try {
            connection.setAutoCommit(false);
            try (PreparedStatement ps = connection.prepareStatement(
              "INSERT INTO Singers (SingerId, FirstName, LastName) "
              + "VALUES (?, ?, ?)")) {
              ps.setLong(1, 17);
              ps.setString(2, "Test");
              ps.setString(3, "Singer 17");
              rowCountInserted = ps.executeUpdate();
            }
            try (PreparedStatement ps = connection.prepareStatement(
              "DELETE FROM Singers WHERE Lastname = ?")) {
              ps.setString(1, "Martin");
              rowCountDeleted = ps.executeUpdate();
            }
            connection.commit();
            break;
          } catch (SQLException e) {
            if (e.getErrorCode() == Code.ABORTED.value()) {
              // Transaction aborted, retry.
            } else {
              throw e;
            }
          }
        }
      }
      System.out.printf("%d record inserted.\n", rowCountInserted);
      System.out.printf("%d record deleted.\n", rowCountDeleted);
    }

Ejecuta una consulta de SQL

Usa la siguiente consulta para mostrar todas las filas de la tabla Albums cuyos títulos comienzan con la letra G:

static void queryWithJdbc(String projectId, String instance,
        String database) throws SQLException {
      String jdbcUrl = getJdbcConnectionUrl(projectId, instance, database);
      try (Connection connection = DriverManager.getConnection(jdbcUrl)) {
        PreparedStatement ps = connection.prepareStatement(
            "SELECT * FROM Albums WHERE AlbumTitle LIKE ?");
        ps.setQueryTimeout(10);
        ps.setString(1, "G%");
        try (java.sql.ResultSet rs = ps.executeQuery()) {
          while (rs.next()) {
            System.out
                .println(String.format("%d %s", rs.getLong("AlbumId"),
                    rs.getString("AlbumTitle")));
          }
        }
      } catch (SQLException e) {
        if (e.getErrorCode() == Code.ABORTED.value()) {
          // Transaction aborted, retry.
        } else {
          throw e;
        }
      }
    }

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.

Qué sigue

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