1. Visão geral
O Cloud Spanner é um RDBMS altamente disponível, escalonável e multirregional. Este codelab vai usar uma menor instância do Cloud Spanner, mas não se esqueça de encerrá-lo quando terminar.
O que você vai aprender
- Como usar o Cloud Spanner para salvar e recuperar dados com o Spring Boot
O que é necessário
Como você usará este tutorial?
Como você classificaria sua experiência com o uso dos serviços do Google Cloud Platform?
2. Configuração e requisitos
Configuração de ambiente autoguiada
- Faça login no Console do Cloud e crie um novo projeto ou reutilize um existente. Crie uma se você ainda não tiver uma conta do Gmail ou do G Suite.
Lembre-se do código do projeto, um nome exclusivo em todos os projetos do Google Cloud. O nome acima já foi escolhido e não servirá para você. Faremos referência a ele mais adiante neste codelab como PROJECT_ID
.
- Em seguida, será necessário ativar o faturamento no Console do Cloud para usar os recursos do Google Cloud.
A execução deste codelab não será muito cara, se for o caso. Siga todas as instruções na seção "Limpeza", que orienta você sobre como encerrar recursos para não incorrer em cobranças além deste tutorial. Novos usuários do Google Cloud estão qualificados para o programa de US$ 300 de avaliação sem custos.
Ativar o Cloud Shell
- No Console do Cloud, clique em Ativar o Cloud Shell.
Se você nunca tiver iniciado o Cloud Shell, verá uma tela intermediária (abaixo da dobra) com a descrição do que ele é. Se esse for o caso, clique em Continuar e você não o verá novamente. Esta é uma tela única:
Leva apenas alguns instantes para provisionar e se conectar ao Cloud Shell.
Essa máquina virtual contém todas as ferramentas de desenvolvimento necessárias. Ela oferece um diretório principal persistente de 5 GB, além de ser executada no Google Cloud. Isso aprimora o desempenho e a autenticação da rede. Praticamente todo o seu trabalho neste codelab pode ser feito em um navegador ou no seu Chromebook.
Depois de se conectar ao Cloud Shell, você já estará autenticado e o projeto já estará configurado com seu ID do projeto.
- Execute o seguinte comando no Cloud Shell para confirmar que você está autenticado:
gcloud auth list
Resposta ao comando
Credentialed Accounts ACTIVE ACCOUNT * <my_account>@<my_domain.com> To set the active account, run: $ gcloud config set account `ACCOUNT`
gcloud config list project
Resposta ao comando
[core] project = <PROJECT_ID>
Se o projeto não estiver configurado, configure-o usando este comando:
gcloud config set project <PROJECT_ID>
Resposta ao comando
Updated property [core/project].
3. Inicializar o Cloud Spanner
Ative a API Cloud Spanner usando a CLI gcloud:
gcloud services enable spanner.googleapis.com
Crie uma instância do Cloud Spanner:
gcloud spanner instances create spanner-instance \ --config=regional-us-central1 \ --nodes=1 --description="A Spanner Instance"
Crie um banco de dados dentro da instância:
gcloud spanner databases create orders \ --instance=spanner-instance
Crie um arquivo schema.ddl
para descrever o esquema de dados:
cat << EOF > schema.ddl CREATE TABLE orders ( order_id STRING(36) NOT NULL, description STRING(255), creation_timestamp TIMESTAMP, ) PRIMARY KEY (order_id); CREATE TABLE order_items ( order_id STRING(36) NOT NULL, order_item_id STRING(36) NOT NULL, description STRING(255), quantity INT64, ) PRIMARY KEY (order_id, order_item_id), INTERLEAVE IN PARENT orders ON DELETE CASCADE; EOF
Aplique o esquema ao banco de dados do Cloud Spanner:
gcloud spanner databases ddl update orders \ --instance=spanner-instance \ --ddl="$(<schema.ddl)"
4. Inicializar um novo aplicativo Java do Spring Boot
No ambiente do Cloud Shell, use o seguinte comando para inicializar um novo aplicativo do Spring Boot:
$ curl https://start.spring.io/starter.tgz \ -d packaging=jar \ -d dependencies=cloud-gcp,web,lombok \ -d baseDir=spanner-example \ -d type=maven-project \ -d bootVersion=3.2.6 | tar -xzvf - $ cd spanner-example
Isso vai criar um novo diretório spanner-example/
com um novo projeto Maven, junto com o pom.xml
do Maven, um wrapper do Maven e um ponto de entrada do aplicativo.
No arquivo pom.xml
, adicione a ativação do Spring Data Cloud Spanner.
spanner-example/pom.xml (em inglês)
<project>
...
<dependencies>
...
<!-- Add Spring Cloud GCP Spanner Starter -->
<dependency>
<groupId>com.google.cloud</groupId>
<artifactId>spring-cloud-gcp-starter-data-spanner</artifactId>
</dependency>
...
</dependencies>
...
</project>
Em "application.properties", configure as informações de conexão do banco de dados do Spanner:
spanner-example/src/main/resources/application.properties
spring.cloud.gcp.spanner.instance-id=spanner-instance spring.cloud.gcp.spanner.database=orders
Verifique se JAVA_HOME
está definido com a versão correta:
export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64/
Recrie o app para verificar se a configuração do Maven está correta:
./mvnw package
5. Criar as entidades
Com o suporte ao Spring Data Spanner do Spring Cloud GCP, você pode usar o Spring Data para criar facilmente um objeto Java e um mapeamento idiomático de ORM para uma tabela do Spanner.
Primeiro, crie uma classe Order Item.
spanner-example/src/main/java/com/example/demo/OrderItem.java
package com.example.demo;
import com.google.cloud.spring.data.spanner.core.mapping.Column;
import com.google.cloud.spring.data.spanner.core.mapping.PrimaryKey;
import com.google.cloud.spring.data.spanner.core.mapping.Table;
@Table(name="order_items")
@Data
class OrderItem {
@PrimaryKey(keyOrder = 1)
@Column(name="order_id")
private String orderId;
@PrimaryKey(keyOrder = 2)
@Column(name="order_item_id")
private String orderItemId;
private String description;
private Long quantity;
}
Para relacionamentos pai/filho no Spanner, você deve usar uma chave primária composta. Neste exemplo, a chave composta é order_id
e order_item_id
.
Em seguida, crie uma classe Order:
spanner-example/src/main/java/com/example/demo/Order.java
package com.example.demo;
import java.time.LocalDateTime;
import java.util.List;
import lombok.Data;
import com.google.cloud.spring.data.spanner.core.mapping.Column;
import com.google.cloud.spring.data.spanner.core.mapping.Interleaved;
import com.google.cloud.spring.data.spanner.core.mapping.PrimaryKey;
import com.google.cloud.spring.data.spanner.core.mapping.Table;
@Table(name="orders")
@Data
public class Order {
@PrimaryKey
@Column(name="order_id")
private String id;
private String description;
@Column(name="creation_timestamp")
private LocalDateTime timestamp;
@Interleaved
private List<OrderItem> items;
}
Essa classe usa a anotação @Interleaved
para criar um relacionamento de um para muitos com os itens do pedido.
6. Criar a interface OrderRepository
Crie a classe OrderRepository
com o seguinte conteúdo:
spanner-example/src/main/java/com/example/demo/OrderRepository.java
package com.example.demo;
import com.google.cloud.spring.data.spanner.repository.SpannerRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface OrderRepository extends SpannerRepository<Order, String> {
}
A interface estende SpannerRepository<Order, String>
, em que Order
é a classe de domínio e String
é o tipo de chave primária. A Spring Data fornecerá automaticamente acesso ao CRUD por meio dessa interface e você não precisará criar nenhum código adicional.
7. Criar um controlador REST para operações básicas
Abra a classe DemoApplication
do aplicativo principal e modifique-a para que fique assim:
spanner-example/src/main/java/com/example/demo/DemoApplication.java
package com.example.demo;
import java.time.LocalDateTime;
import java.util.UUID;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.server.ResponseStatusException;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
@RestController
class OrderController {
private final OrderRepository orderRepository;
OrderController(OrderRepository orderRepository) {
this.orderRepository = orderRepository;
}
@GetMapping("/api/orders/{id}")
public Order getOrder(@PathVariable String id) {
return orderRepository.findById(id)
.orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, id + " not found"));
}
@PostMapping("/api/orders")
public String createOrder(@RequestBody Order order) {
// Spanner currently does not auto generate IDs
// Generate UUID on new orders
order.setId(UUID.randomUUID().toString());
order.setTimestamp(LocalDateTime.now());
order.getItems().forEach(item -> {
// Assign parent ID, and also generate child ID
item.setOrderId(order.getId());
item.setOrderItemId(UUID.randomUUID().toString());
});
Order saved = orderRepository.save(order);
return saved.getId();
}
}
8. Execute o aplicativo
Recrie e execute o aplicativo.
./mvnw spring-boot:run
Isso deve iniciar corretamente e escutar na porta 8080.
É possível postar um registro de pedido no endpoint:
curl -H"Content-Type: application/json" -d'{"description": "My orders", "items": [{"description": "Android Phone", "quantity": "1"}]}' \ http://localhost:8080/api/orders
A resposta deve conter o UUID
do pedido.
É possível recuperar o pedido com o UUID
:
curl http://localhost:8080/api/orders/REPLACE_WITH_ORDER_UUID
Para conferir como os dados são armazenados no Cloud Spanner, acesse o console do Cloud e navegue até Spanner → Instância do Spanner → banco de dados de pedidos → tabela de pedidos → Dados.
9. Limpar
Para limpar, exclua a instância do Spanner para que ela não receba mais cobranças.
gcloud spanner instances delete spanner-instance -q
10. Parabéns!
Neste codelab, você criou um aplicativo de CLI interativo que pode armazenar e recuperar dados do Cloud Spanner.
Saiba mais
- Cloud Spanner: https://cloud.google.com/spanner/
- Projeto do Spring no GCP: https://googlecloudplatform.github.io/spring-cloud-gcp/reference/html/
- Repositório do GitHub do Spring no GCP: https://github.com/spring-cloud/spring-cloud-gcp
- Java no Google Cloud Platform: https://cloud.google.com/java/
Licença
Este conteúdo está sob a licença Atribuição 2.0 Genérica da Creative Commons.