1. 概览
Cloud Spanner 是一个可用性高、可横向扩容的多区域 RDBMS。此 Codelab 将使用 Cloud Spanner 的最小实例,但请务必在完成后关闭它!
学习内容
- 如何使用 Cloud Spanner 通过 Spring Boot 保存和检索数据
所需条件
您打算如何使用本教程?
您如何评价自己在使用 Google Cloud Platform 服务方面的经验水平?
<ph type="x-smartling-placeholder">2. 设置和要求
自定进度的环境设置
请记住项目 ID,它在所有 Google Cloud 项目中都是唯一的名称(上述名称已被占用,您无法使用,抱歉!)。它稍后将在此 Codelab 中被称为 PROJECT_ID。
- 接下来,您需要在 Cloud 控制台中启用结算功能,才能使用 Google Cloud 资源。
运行此 Codelab 应该不会产生太多的费用(如果有费用的话)。请务必按照“清理”部分部分,其中会指导您如何关停资源,以免产生超出本教程范围的结算费用。Google Cloud 的新用户符合参与 $300 USD 免费试用计划的条件。
激活 Cloud Shell
- 在 Cloud Console 中,点击激活 Cloud Shell
。
如果您以前从未启动过 Cloud Shell,将看到一个中间屏幕(在折叠下面),描述它是什么。如果是这种情况,请点击继续(您将永远不会再看到它)。一次性屏幕如下所示:
预配和连接到 Cloud Shell 只需花几分钟时间。
这个虚拟机已加载了您需要的所有开发工具。它提供了一个持久的 5GB 主目录,并且在 Google Cloud 中运行,大大增强了网络性能和身份验证。只需使用一个浏览器或 Google Chromebook 即可完成本 Codelab 中的大部分(甚至全部)工作。
在连接到 Cloud Shell 后,您应该会看到自己已通过身份验证,并且相关项目已设置为您的项目 ID:
- 在 Cloud Shell 中运行以下命令以确认您已通过身份验证:
gcloud auth list
命令输出
Credentialed Accounts ACTIVE ACCOUNT * <my_account>@<my_domain.com> To set the active account, run: $ gcloud config set account `ACCOUNT`
gcloud config list project
命令输出
[core] project = <PROJECT_ID>
如果不是上述结果,您可以使用以下命令进行设置:
gcloud config set project <PROJECT_ID>
命令输出
Updated property [core/project].
3. 初始化 Cloud Spanner
使用 gcloud CLI 启用 Cloud Spanner API:
gcloud services enable spanner.googleapis.com
创建 Cloud Spanner 实例:
gcloud spanner instances create spanner-instance \ --config=regional-us-central1 \ --nodes=1 --description="A Spanner Instance"
在实例中创建数据库:
gcloud spanner databases create orders \ --instance=spanner-instance
创建一个 schema.ddl 文件来描述数据架构:
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
将架构应用于 Cloud Spanner 数据库:
gcloud spanner databases ddl update orders \ --instance=spanner-instance \ --ddl="$(<schema.ddl)"
4. 引导新的 Spring Boot Java 应用
在 Cloud Shell 环境中,使用以下命令初始化和引导新的 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
这将使用一个新的 Maven 项目、Maven 的 pom.xml(一个 Maven 封装容器)和一个应用入口点来创建一个新的 spanner-example/ 目录。
在 pom.xml 文件中,添加 Spring Data Cloud Spanner 入门版。
spanner-example/pom.xml
<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> 在 application.properties 中,配置 Spanner 数据库连接信息:
spanner-example/src/main/resources/application.properties
spring.cloud.gcp.spanner.instance-id=spanner-instance spring.cloud.gcp.spanner.database=orders
确保将 JAVA_HOME 设置为正确的版本:
export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64/
重新构建应用以确保您的 Maven 配置正确无误:
./mvnw package
5. 创建实体
借助 Spring Cloud GCP 的 Spring Data Spanner 支持,您可以轻松创建 Java 对象,并使用 Spring Data 轻松创建到 Spanner 表的惯用 ORM 映射。
首先,创建一个 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; } 对于 Spanner 中的父/子关系,您应该使用复合主键。在此示例中,复合键为 order_id 和 order_item_id。
接下来,创建一个 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; } 此类使用 @Interleaved 注解创建与“订单商品”的一对多关系。
6. 创建 OrderRepository 接口
使用以下内容创建 OrderRepository 类:
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> { } 该接口扩展了 SpannerRepository<Order, String>,其中 Order 是网域类,String 是主键类型。Spring Data 会自动通过此界面提供 CRUD 访问权限,您无需创建任何其他代码。
7. 为基本操作创建 REST 控制器
打开主应用 DemoApplication 类,并按如下所示对其进行修改:
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. 运行应用
重新构建并运行应用!
./mvnw spring-boot:run
此命令应会正确启动并监听端口 8080。
您可以将订单记录发布到端点:
curl -H"Content-Type: application/json" -d'{"description": "My orders", "items": [{"description": "Android Phone", "quantity": "1"}]}' \ http://localhost:8080/api/orders 它应该以订单的 UUID 做出响应。
然后,您可以使用 UUID 检索订单:
curl http://localhost:8080/api/orders/REPLACE_WITH_ORDER_UUID
如需查看 Cloud Spanner 中数据的存储方式,请前往 Cloud Console,然后依次前往 Spanner → Spanner 实例 → 订单数据库 → 订单表 → 数据。

9. 清理
如需进行清理,请删除 Spanner 实例,使其不再产生费用!
gcloud spanner instances delete spanner-instance -q
10. 恭喜!
在此 Codelab 中,您创建了一个交互式 CLI 应用,该应用可以在 Cloud Spanner 中存储和检索数据!
了解详情
- Cloud Spanner:https://cloud.google.com/spanner/
- GCP 项目的 Spring:https://googlecloudplatform.github.io/spring-cloud-gcp/reference/html/
- GCP GitHub 代码库上的 Spring:https://github.com/spring-cloud/spring-cloud-gcp
- Google Cloud Platform 上的 Java:https://cloud.google.com/java/
许可
此作品已获得 Creative Commons Attribution 2.0 通用许可授权。