Introdução ao Spanner em Java

Objetivos

Neste tutorial, você vai conhecer as seguintes etapas usando a biblioteca de cliente do Spanner para Java:

  • Crie uma instância e um banco de dados do Spanner.
  • Gravar, ler e executar consultas SQL em dados contidos no banco de dados.
  • Atualizar o esquema do banco de dados.
  • Atualizar dados usando uma transação de leitura e gravação.
  • Adicionar um índice secundário ao banco de dados.
  • Usar o índice para ler e executar consultas SQL nos dados.
  • Recuperar dados usando uma transação somente leitura.

Custos

Neste tutorial, usamos o Spanner, que é um componente faturável do Google Cloud. Para informações sobre o custo do uso do Spanner, consulte Preços.

Antes de começar

Conclua as etapas descritas em Configurar, que abrangem a criação e a configuração de um projeto padrão do Google Cloud , o faturamento, a API Cloud Spanner e a configuração do OAuth 2.0 para receber credenciais de autenticação para usar a API Cloud Spanner.

Especificamente, execute gcloud auth application-default login para configurar o ambiente de desenvolvimento local com credenciais de autenticação.

Prepare seu ambiente Java local

  1. Instale os seguintes itens na sua máquina de desenvolvimento se ainda não estiverem instalados:

  2. Clone o repositório do app de amostra na máquina local:

    git clone https://github.com/googleapis/google-cloud-java.git
    
  3. Mude para o diretório que contém o exemplo de código do Spanner:

    cd google-cloud-java/java-spanner/samples/snippets
    
  4. Gere o arquivo JAR de amostra:

    mvn clean package
    

Criar uma instância

Ao usar o Spanner pela primeira vez, é necessário criar uma instância, que é uma alocação de recursos usados pelos bancos de dados do Spanner. Ao criar uma instância, escolha uma configuração que determine onde os dados serão armazenados e também o número de nós a serem usados. Isso determina a quantidade de recursos de exibição e armazenamento na instância.

Consulte Criar uma instância para saber como criar uma instância do Spanner usando um dos seguintes métodos. Você pode nomear sua instância como test-instance para usar com outros tópicos neste documento que fazem referência a uma instância chamada test-instance.

  • A Google Cloud CLI
  • O console do Google Cloud
  • Uma biblioteca de cliente (C++, C#, Go, Java, Node.js, PHP, Python ou Ruby)

Consultar os arquivos de amostra

O repositório de amostras contém um exemplo que mostra como usar o Spanner com Java.

Criar um banco de dados

GoogleSQL

java -jar target/spanner-snippets/spanner-google-cloud-samples.jar \
createdatabase test-instance example-db

PostgreSQL

java -jar target/spanner-snippets/spanner-google-cloud-samples.jar \
createpgdatabase test-instance example-db

Você verá:

Created database [example-db]
O código a seguir cria um banco de dados e duas tabelas nele.

GoogleSQL

static void createDatabase(DatabaseAdminClient dbAdminClient,
    InstanceName instanceName, String databaseId) {
  CreateDatabaseRequest createDatabaseRequest =
      CreateDatabaseRequest.newBuilder()
          .setCreateStatement("CREATE DATABASE `" + databaseId + "`")
          .setParent(instanceName.toString())
          .addAllExtraStatements(Arrays.asList(
              "CREATE TABLE Singers ("
                  + "  SingerId   INT64 NOT NULL,"
                  + "  FirstName  STRING(1024),"
                  + "  LastName   STRING(1024),"
                  + "  SingerInfo BYTES(MAX),"
                  + "  FullName STRING(2048) AS "
                  + "  (ARRAY_TO_STRING([FirstName, LastName], \" \")) STORED"
                  + ") PRIMARY KEY (SingerId)",
              "CREATE TABLE Albums ("
                  + "  SingerId     INT64 NOT NULL,"
                  + "  AlbumId      INT64 NOT NULL,"
                  + "  AlbumTitle   STRING(MAX)"
                  + ") PRIMARY KEY (SingerId, AlbumId),"
                  + "  INTERLEAVE IN PARENT Singers ON DELETE CASCADE")).build();
  try {
    // Initiate the request which returns an OperationFuture.
    com.google.spanner.admin.database.v1.Database db =
        dbAdminClient.createDatabaseAsync(createDatabaseRequest).get();
    System.out.println("Created database [" + db.getName() + "]");
  } catch (ExecutionException e) {
    // If the operation failed during execution, expose the cause.
    throw (SpannerException) e.getCause();
  } catch (InterruptedException e) {
    // Throw when a thread is waiting, sleeping, or otherwise occupied,
    // and the thread is interrupted, either before or during the activity.
    throw SpannerExceptionFactory.propagateInterrupt(e);
  }
}

PostgreSQL

static void createPostgreSqlDatabase(
    DatabaseAdminClient dbAdminClient, String projectId, String instanceId, String databaseId) {
  final CreateDatabaseRequest request =
      CreateDatabaseRequest.newBuilder()
          .setCreateStatement("CREATE DATABASE \"" + databaseId + "\"")
          .setParent(InstanceName.of(projectId, instanceId).toString())
          .setDatabaseDialect(DatabaseDialect.POSTGRESQL).build();

  try {
    // Initiate the request which returns an OperationFuture.
    Database db = dbAdminClient.createDatabaseAsync(request).get();
    System.out.println("Created database [" + db.getName() + "]");
  } catch (ExecutionException e) {
    // If the operation failed during execution, expose the cause.
    throw (SpannerException) e.getCause();
  } catch (InterruptedException e) {
    // Throw when a thread is waiting, sleeping, or otherwise occupied,
    // and the thread is interrupted, either before or during the activity.
    throw SpannerExceptionFactory.propagateInterrupt(e);
  }
}
static void createTableUsingDdl(DatabaseAdminClient dbAdminClient, DatabaseName databaseName) {
  try {
    // Initiate the request which returns an OperationFuture.
    dbAdminClient.updateDatabaseDdlAsync(
        databaseName,
        Arrays.asList(
            "CREATE TABLE Singers ("
                + "  SingerId   bigint NOT NULL,"
                + "  FirstName  character varying(1024),"
                + "  LastName   character varying(1024),"
                + "  SingerInfo bytea,"
                + "  FullName character varying(2048) GENERATED "
                + "  ALWAYS AS (FirstName || ' ' || LastName) STORED,"
                + "  PRIMARY KEY (SingerId)"
                + ")",
            "CREATE TABLE Albums ("
                + "  SingerId     bigint NOT NULL,"
                + "  AlbumId      bigint NOT NULL,"
                + "  AlbumTitle   character varying(1024),"
                + "  PRIMARY KEY (SingerId, AlbumId)"
                + ") INTERLEAVE IN PARENT Singers ON DELETE CASCADE")).get();