使用 Cloud Datastore 的 Spring Boot 應用程式

1. 總覽

Google Cloud Datastore 是專為自動調整資源配置、提供高效能及便利開發應用程式所建構的 NoSQL 文件資料庫。

課程內容

  • 如何使用 Cloud Datastore 在 Spring Boot 中儲存及擷取 Java 物件

軟硬體需求

您會如何使用本教學課程?

僅閱讀 閱讀並完成練習

您對使用 Google Cloud Platform 服務的體驗有何評價?

新手 中級 熟練

2. 設定和需求

自修實驗室環境設定

  1. 登入 Google Cloud 控制台,然後建立新專案或重複使用現有專案。如果沒有 Gmail 或 Google Workspace 帳戶,請先建立帳戶

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • 專案名稱是這個專案參與者的顯示名稱。這是 Google API 未使用的字元字串。你隨時可以更新。
  • 專案 ID 在所有 Google Cloud 專案中都是不重複的,而且設定後即無法變更。Cloud 控制台會自動產生專屬字串,通常您不需要在意該字串為何。在大多數程式碼研究室中,您需要參照專案 ID (通常標示為 PROJECT_ID)。如果您不喜歡產生的 ID,可以產生另一個隨機 ID。你也可以嘗試使用自己的名稱,看看是否可用。完成這個步驟後就無法變更,且專案期間會維持不變。
  • 請注意,有些 API 會使用第三個值,也就是「專案編號」。如要進一步瞭解這三種值,請參閱說明文件
  1. 接著,您需要在 Cloud 控制台中啟用帳單,才能使用 Cloud 資源/API。完成這個程式碼研究室的費用不高,甚至可能完全免費。如要關閉資源,避免在本教學課程結束後繼續產生費用,請刪除您建立的資源或專案。Google Cloud 新使用者可參加價值$300 美元的免費試用計畫。

啟用 Cloud Shell

  1. 在 Cloud 控制台,點選「啟用 Cloud Shell」 圖示 853e55310c205094.png

55efc1aaa7a4d3ad.png

如果您是首次啟動 Cloud Shell,系統會顯示中繼畫面,說明這個指令列環境。如果出現中繼畫面,請按一下「繼續」

9c92662c6a846a5c.png

佈建並連至 Cloud Shell 預計只需要幾分鐘。

9f0e51b578fecce5.png

這部虛擬機器已載入所有必要的開發工具,並提供永久的 5 GB 主目錄,而且可在 Google Cloud 運作,大幅提升網路效能並強化驗證功能。本程式碼研究室幾乎所有工作都可在瀏覽器上完成。

連至 Cloud Shell 後,您應該會看到驗證已完成,專案也已設為獲派的專案 ID。

  1. 在 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`
  1. 在 Cloud Shell 中執行下列指令,確認 gcloud 指令知道您的專案:
gcloud config list project

指令輸出

[core]
project = <PROJECT_ID>

如未設定,請輸入下列指令手動設定專案:

gcloud config set project <PROJECT_ID>

指令輸出

Updated property [core/project].

3. 初始化 Cloud Datastore

GCP 主控台中,前往「選單」->「Datastore」(位於「儲存空間」部分),或按一下這裡

如果您從未在目前專案中使用 Datastore,系統會顯示「選取 Cloud Firestore 模式」畫面。選取「Datastore mode」(資料儲存模式) 選項。

f938295c7ff297f4.png

接著會看到「選擇資料的儲存位置」畫面。選取「us-east1」或其他區域位置,然後按一下「建立資料庫」:

916ac84fec10fae7.png

4. 啟動新的 Spring Boot Java 應用程式

在 Cloud Shell 環境中,使用下列指令初始化並啟動新的 Spring Boot 應用程式:

$ curl https://start.spring.io/starter.tgz \
  -d packaging=war \
  -d dependencies=cloud-gcp \
  -d type=maven-project \
  -d baseDir=datastore-example \
  -d bootVersion=3.0.5 | tar -xzvf -

這會建立新的 datastore-example/ 目錄和新的 Maven 專案,以及 Maven 的 pom.xml、Maven 包裝函式和應用程式進入點。

我們的應用程式會提供 CLI,供使用者輸入指令並查看結果。我們會建立類別來代表書籍,然後使用 Datastore Repository 將其儲存至 Cloud Datastore。

我們還需要在 pom.xml 中新增一個必要的依附元件。

按一下 Cloud Shell 選單中的「開啟編輯器」,開啟網頁程式碼編輯器。

6d823258c76a7452.png

編輯器載入後,請修改 pom.xml 檔案,加入 Google Cloud Datastore Starter 和 Spring Shell Starter 依附元件:

pom.xml

<project>
  ...
  <dependencies>
        ...
        <!-- Add GCP Datastore Starter -->
        <dependency>
                <groupId>com.google.cloud</groupId>
                <artifactId>spring-cloud-gcp-starter-data-datastore</artifactId>
        </dependency>

        <!-- Add Spring Shell Starter -->
        <dependency>
                <groupId>org.springframework.shell</groupId>
                <artifactId>spring-shell-starter</artifactId>
                <version>3.0.2</version>
        </dependency>

  </dependencies>
</project>

5. 建立 Book 類別

使用編輯器建立 Book 類別,並加入以下內容:

datastore-example/src/main/java/com/example/demo/Book.java

package com.example.demo;

import com.google.cloud.spring.data.datastore.core.mapping.Entity;
import org.springframework.data.annotation.Id;

@Entity(name = "books")
public class Book {
  @Id
  Long id;

  String title;

  String author;

  int year;

  public Book(String title, String author, int year) {
    this.title = title;
    this.author = author;
    this.year = year;
  }

  public long getId() {
    return this.id;
  }

  @Override
  public String toString() {
    return "Book{" +
        "id=" + this.id +
        ", title='" + this.title + '\'' +
        ", author='" + this.author + '\'' +
        ", year=" + this.year +
        '}';
  }
}

如您所見,這是簡單的 POJO。這個類別會使用 @Entity 註解,指出該類別可儲存在 Datastore 中,並提供種類名稱 (將種類視為 SQL 資料庫中的資料表,詳情請參閱說明文件)。種類名稱為選用項目,如果省略,系統會根據類別名稱產生種類名稱。

請注意,我們使用 @Idid 屬性加上註解。這表示我們希望這個欄位做為 Datastore 金鑰的 ID 部分。每個 Datastore 實體都需要 ID。支援的類型包括 StringLong

我們覆寫 toString 方法,讓物件的字串表示法更易於閱讀,這在列印物件時會很有用。

6. 建立 BookRepository 介面

建立 BookRepository 類別,並加入以下內容:

datastore-example/src/main/java/com/example/demo/BookRepository.java

package com.example.demo;

import java.util.List;

import com.google.cloud.spring.data.datastore.repository.DatastoreRepository;


public interface BookRepository extends DatastoreRepository<Book, Long> {

  List<Book> findByAuthor(String author);

  List<Book> findByYearGreaterThan(int year);

  List<Book> findByAuthorAndYear(String author, int year);
}

介面會擴充 DatastoreRepository<Book, Long>,其中 Book 是網域類別,LongId 型別。我們會在存放區中宣告三種查詢方法,系統會在幕後自動產生實作項目。

第一個是 findByAuthor。如您所料,這個方法的實作會執行查詢,在條件篩選器中使用使用者提供的值,判斷是否與作者欄位相等。

findByYearGreaterThan 方法會執行查詢,篩選出年份欄位大於使用者提供的值。

findByAuthorAndYear 執行查詢,尋找作者和年份欄位與使用者提供的值相符的實體。

7. 建立互動式 CLI 應用程式

開啟主要應用程式 DemoApplication 類別,並修改成如下所示:

datastore-example/src/main/java/com/example/demo/DemoApplication.java

package com.example.demo;

import java.util.List;

import com.google.common.collect.Lists;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.shell.standard.ShellComponent;
import org.springframework.shell.standard.ShellMethod;

@ShellComponent
@SpringBootApplication
public class DemoApplication {
  @Autowired
  BookRepository bookRepository;

  public static void main(String[] args) {
     SpringApplication.run(DemoApplication.class, args);
  }

  @ShellMethod("Saves a book to Cloud Datastore: save-book <title> <author> <year>")
  public String saveBook(String title, String author, int year) {
     Book savedBook = this.bookRepository.save(new Book(title, author, year));
     return savedBook.toString();
  }

  @ShellMethod("Loads all books")
  public String findAllBooks() {
     Iterable<Book> books = this.bookRepository.findAll();
     return Lists.newArrayList(books).toString();
  }

  @ShellMethod("Loads books by author: find-by-author <author>")
  public String findByAuthor(String author) {
     List<Book> books = this.bookRepository.findByAuthor(author);
     return books.toString();
  }

  @ShellMethod("Loads books published after a given year: find-by-year-after <year>")
  public String findByYearAfter(int year) {
     List<Book> books = this.bookRepository.findByYearGreaterThan(year);
     return books.toString();
  }

  @ShellMethod("Loads books by author and year: find-by-author-year <author> <year>")
  public String findByAuthorYear(String author, int year) {
     List<Book> books = this.bookRepository.findByAuthorAndYear(author, year);
     return books.toString();
  }

  @ShellMethod("Removes all books")
  public void removeAllBooks() {
     this.bookRepository.deleteAll();
  }
}

請注意,我們如何使用 @ShellComponent 為類別加上註解。這會通知 Spring,我們要將這個類別做為 CLI 指令的來源。以 @ShellMethod 註解的方法會以 CLI 指令的形式公開在應用程式中。

這裡會使用在 BookRepository 介面中宣告的方法:findByAuthorfindByYearGreaterThanfindByAuthorAndYear。此外,我們還使用了三種內建方法:savefindAlldeleteAll

請參閱 saveBook 方法。我們會使用使用者提供的書名、作者和年份值,建立 Book 物件。如您所見,我們並未提供 id 值,因此系統會在儲存時自動分配並指派給 id 欄位。save 方法會接受 Book 類型的物件,並將其儲存至 Cloud Datastore。系統會傳回填入所有欄位的 Book 物件,包括 id 欄位。最後,我們會傳回這個物件的字串表示法。

其餘方法也以類似方式運作:接受傳遞至適當存放區方法的參數,並傳回字串化結果。

8. 執行應用程式

如要建構及啟動應用程式,請先確認 JAVA_HOME 已設為正確版本:

$ export JAVA_HOME=/usr/lib/jvm/java-1.17.0-openjdk-amd64

在 Cloud Shell 中執行這項指令 (從專案 datastore-example/ 的根目錄,也就是 pom.xml 所在的位置):

$ ./mvnw spring-boot:run
export JAVA_HOME=/usr/lib/jvm/java-1.17.0-openjdk-amd64

建構階段完成後,畫面上會顯示 Spring 標誌和殼層提示:

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v3.0.5)



shell:>

現在可以試試先前定義的指令。如要查看指令清單,請使用 help 指令:

shell:> help
...
find-all-books: Loads all books
find-by-author: Loads books by author: find-by-author <author>
find-by-author-year: Loads books by author and year: find-by-author-year <author> <year>
find-by-year-after: Loads books published after a given year: find-by-year-after <year>
remove-all-books: Removes all books
save-book: Saves a book to Cloud Datastore: save-book <title> <author> <year>

請嘗試按照下列步驟操作:

  1. 使用 save-book 指令建立幾本書
  2. 使用 find-all-books 指令執行搜尋
  3. 尋找特定作者的書籍:find-by-author <author>
  4. 尋找特定年份後出版的書籍:find-by-year-after <year>
  5. 依特定作者和年份尋找書籍:find-by-author-year <author> <year>

9. 使用網頁介面查看 Datastore 中儲存的內容

如要查看實體在 Cloud Datastore 中的儲存方式,請前往 GCP 主控台。視需要,在種類欄位中輸入「books」。

5fab21a6c89f45a.png

10. 清理

如要清除所有書籍,請從應用程式殼層使用適當命名的 remove-all-books 指令。

shell:> remove-all-books

如要結束應用程式,請使用 quit 指令,然後按一下 Ctrl+C

11. 恭喜!

在本程式碼研究室中,您已建立互動式 CLI 應用程式,可從 Cloud Datastore 儲存及擷取物件!

瞭解詳情

授權

這項內容採用的授權為 Creative Commons 姓名標示 2.0 通用授權。