程式碼研究室簡介
1. 總覽
Google Cloud Datastore 是一個 NoSQL 文件資料庫,專為自動調整資源配置、高效能及容易開發應用程式而設計。
您將會瞭解的內容
- 如何在 Spring Boot 中使用 Cloud Datastore 儲存及擷取 Java 物件
軟硬體需求
您要如何使用本教學課程?
您對於 Google Cloud Platform 服務的使用體驗評價如何?
2. 設定和需求
自行調整環境設定
如果您還沒有 Google 帳戶 (Gmail 或 Google Apps),請先建立帳戶。登入 Google Cloud Platform 主控台 (console.cloud.google.com),然後建立新專案:
提醒您,專案編號是所有 Google Cloud 專案的不重複名稱 (使用上述名稱後就無法使用,敬請見諒!)此程式碼研究室稍後將稱為 PROJECT_ID
。
接著,您必須在 Cloud Console 中啟用計費功能,才能使用 Google Cloud 資源。
完成這個程式碼研究室的成本應該不會超過新臺幣 $300 元,但如果您決定繼續使用更多資源,或是讓資源繼續運作 (請參閱本文件結尾的「清除設定」一節),就有可能需要更多成本。
新加入 Google Cloud Platform 的使用者可免費試用$300 美元。
啟用 Google Cloud Shell
在 GCP 主控台中,按一下右上角的工具列的 Cloud Shell 圖示:
然後按一下 [Start Cloud Shell]。
佈建和連線至環境只需要幾分鐘的時間:
這部虛擬機器已載入所有您需要的開發工具。這項服務提供永久性的 5GB 主目錄,可在 Google Cloud 中運作,大幅提升網路效能和驗證效能。在這個研究室中,您可以透過瀏覽器或 Google Chromebook 完成大部分的工作。
連線至 Cloud Shell 之後,您應該會看到您已經通過驗證,且專案已經設定為 PROJECT_ID。
在 Cloud Shell 中執行下列指令,確認您的身分已通過驗證:
gcloud auth list
指令輸出
Credentialed accounts: - <myaccount>@<mydomain>.com (active)
gcloud config list project
指令輸出
[core] project = <PROJECT_ID>
如果沒有,則可使用下列指令設定:
gcloud config set project <PROJECT_ID>
指令輸出
Updated property [core/project].
3. 初始化 Cloud Datastore
在 GCP 主控台中,瀏覽至 [Menu] (選單) -> Datastore (位於「Storage」(儲存空間) 區段)。
如果您從未在目前的專案中使用 Datastore,便會看到「選取 Cloud Firestore 模式」畫面。選取 [quot;Datastore mode"] 選項。
之後,您會看到「選擇資料儲存位置」畫面。選取 us-east1 或任何其他地區位置,然後按一下 [建立資料庫]。
4. 啟動新的 Spring Boot Java 應用程式
在 CloudShell 環境中,使用下列指令來初始化並啟動新的 Spring Boot 應用程式:
$ curl https://start.spring.io/starter.tgz \ -d packaging=war \ -d dependencies=cloud-gcp \ -d baseDir=datastore-example \ -d bootVersion=2.1.1.RELEASE | tar -xzvf -
這項操作會建立新的 datastore-example/
目錄,其中包含新的 Maven 專案、Maven 和 pom.xml
,以及 Maven 包裝函式和應用程式進入點。
我們的應用程式將提供 CLI,讓使用者能輸入指令並查看結果。我們會建立一個類別來代表書籍,並使用 Datastore Repository 將書籍儲存至 Cloud Datastore。
我們也需要為 pom.xml
新增一個額外的相依關係。
在 Cloud Shell 選單中,按一下 [Launch code editor] (啟動程式碼編輯器),開啟「Web Code Editor」(網頁編輯器)。
在編輯器載入後,修改 pom.xml
檔案以新增 Spring Data Cloud Datastore 的 Spring Boot 依附元件:
pom.xml
<project>
...
<dependencies>
...
<!-- Add GCP Datastore Starter -->
<dependency>
<groupId>org.springframework.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>2.0.0.RELEASE</version>
</dependency>
</dependencies>
</project>
5. 建立圖書類別
使用編輯器建立含有下列內容的 Book
類別:
datastore-example/src/main/java/com/example/demo/Book.java
package com.example.demo;
import org.springframework.cloud.gcp.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 資料庫中的資料表,詳情請參閱說明文件)。種類名稱為選填,如果省略,則會根據類別名稱產生種類名稱。
請注意,我們已為 @Id
新增 id
屬性的註解。表示要使用這個欄位做為 Datastore Key 的 ID 部分。每個 Datastore 實體都必須具備識別碼。支援的類型為 String
和 Long
。
我們會覆寫 toString
方法,以更易於閱讀物件的字串,而這在列印物件時相當實用。
別忘了儲存檔案!
6. 建立 BookRepository 介面
建立含有下列內容的 BookRepository
類別:
datastore-example/src/main/java/com/example/demo/BookRepository.java
package com.example.demo;
import java.util.List;
import org.springframework.cloud.gcp.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
是網域類別,Long
則是 Id
類型。我們會在存放區中宣告三種查詢方法,以在背景自動產生實作。
第一個是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 介面中宣告的方法:findByAuthor
、findByYearGreaterThan
、findByAuthorAndYear
。我們也使用三種內建方法:save
、findAll
和 deleteAll
。
讓我們看看saveBook
方法。我們會根據使用者提供的值,建立書名、作者和年份的 Book
物件。如您所見,我們未提供 id
值,因此在儲存時,它會自動分配並指派至 id 欄位。save
方法可接受 Book
類型的物件,並將其儲存至 Cloud Datastore。會傳回一個已填入所有欄位的 Book
物件,包括 id
欄位。最後,我們會傳回此物件的字串表示法。
其他方法則運作方式類似:它們會在參數中傳遞至適當的存放區方法,並傳回字串化結果。
8. 執行應用程式
如要建構並啟動應用程式,請在 Cloud Shell 中執行以下指令 (以「pom.xml
」所在的專案 datastore-example/
根目錄為準):
$ mvn spring-boot:run
成功的建構階段結束後,系統會顯示春季標誌,並顯示殼層提示:
. ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.1.1.RELEASE) 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>
建議您試試下列指令:
- 使用
save-book
指令建立幾本書 - 使用
find-all-books
指令執行搜尋 - 尋找特定作者 (
find-by-author <author>
) 的書籍 - 尋找一年後 (
find-by-year-after <year>
) 出版的書籍 - 依特定作者和年份 (
find-by-author-year <author> <year>
) 尋找書籍
9. 使用網頁介面查看 Datastore 中儲存的資料
如要瞭解實體在 Cloud Datastore 中的儲存方式,請前往 GCP 主控台,然後依序前往 [選單] -> [資料儲存庫] (位於 [儲存空間] 部分) -> <實體> (選取 [預設] 命名空間和必要項目)。
10. 清除所用資源
如要清理相片,請在應用程式命令介面使用自動調整名稱的 remove-all-books
指令移除所有書籍。
shell:> remove-all-books
如要結束應用程式,請使用 quit 指令,然後按下 Ctrl+C 鍵。
11. 恭喜!
在這個程式碼研究室中,您已建立互動式 CLI 應用程式,可從 Cloud Datastore 儲存及擷取物件!
瞭解詳情
- Cloud Datastore:https://cloud.google.com/datastore/
- Spring Shell:https://projects.spring.io/spring-shell/
- Spring 搭配 GCP 專案:http://cloud.spring.io/spring-cloud-gcp/
- GCP 存放區上的 Spring:https://github.com/spring-cloud/spring-cloud-gcp
- 在 Google Cloud Platform 中使用 Java:https://cloud.google.com/java/
授權
本作品採用創用 CC 姓名標示 2.0 一般授權。