1. 總覽
Cloud Spanner 是可用性高、可水平擴充的多區域 RDBMS。此程式碼研究室將使用最小的 Cloud Spanner 執行個體,但別忘了在操作完成後關閉!
課程內容
- 如何透過 Cloud Spanner 透過 Spring Boot 儲存及擷取資料
軟硬體需求
您會如何使用這個教學課程?
根據您使用 Google Cloud Platform 服務的經驗,您會給予什麼評價?
2. 設定和需求
自修環境設定
提醒您,專案 ID 是所有 Google Cloud 專案的專屬名稱 (已經有人使用上述名稱,很抱歉對您不符!)。稍後在本程式碼研究室中會稱為 PROJECT_ID
。
- 接下來,您需要在 Cloud 控制台中啟用計費功能,才能使用 Google Cloud 資源。
執行這個程式碼研究室並不會產生任何費用,如果有的話。請務必依照「清除所用資源」一節指示本節將說明如何關閉資源,這樣您就不會產生本教學課程結束後產生的費用。Google Cloud 的新使用者符合 $300 美元免費試用計畫的資格。
啟用 Cloud Shell
- 在 Cloud 控制台中,按一下「啟用 Cloud Shell」圖示 。
如果您從未啟動 Cloud Shell,您會看見中繼畫面 (需捲動位置),說明螢幕內容。如果出現這種情況,請按一下「繼續」 (之後不會再顯示)。以下是單次畫面的外觀:
佈建並連線至 Cloud Shell 只需幾分鐘的時間。
這部虛擬機器都裝載了您需要的所有開發工具。提供永久的 5 GB 主目錄,而且在 Google Cloud 中運作,大幅提高網路效能和驗證能力。在本程式碼研究室中,您的大部分作業都可以透過瀏覽器或 Chromebook 完成。
連線至 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
這項操作會建立新的 spanner-example/
目錄,其中包含新的 Maven 專案,以及 Maven 的 pom.xml
、Maven 包裝函式和應用程式進入點。
在 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 支援功能,您就能使用 Spring Data 輕鬆建立 Java 物件,以及與 Spanner 資料表慣用的 ORM 對應。
首先,請建立「訂單商品」類別。
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
。
接著,請建立訂單類別:
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 控制台,然後依序前往「Spanner」→「Spanner 執行個體」→「訂單資料庫」→「訂單資料表」→「資料」,
9. 清除所用資源
如要清除所用資源,請刪除 Spanner 執行個體,避免執行個體繼續產生費用!
gcloud spanner instances delete spanner-instance -q
10. 恭喜!
在本程式碼研究室中,您已建立互動式 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/
授權
這項內容採用的是創用 CC 姓名標示 2.0 通用授權。