1. 概览
Google Cloud Datastore 是一个 NoSQL 文档数据库,能够自动扩缩、具备出色的性能,并且易于进行应用开发。
学习内容
- 如何在 Spring Boot 中使用 Cloud Datastore 保存和检索 Java 对象
所需条件
您打算如何使用本教程?
您如何评价自己在使用 Google Cloud Platform 服务方面的经验水平?
<ph type="x-smartling-placeholder">2. 设置和要求
自定进度的环境设置
- 登录 Google Cloud 控制台,然后创建一个新项目或重复使用现有项目。如果您还没有 Gmail 或 Google Workspace 账号,则必须创建一个。



- 项目名称是此项目参与者的显示名称。它是 Google API 尚未使用的字符串。您可以随时对其进行更新。
- 项目 ID 在所有 Google Cloud 项目中是唯一的,并且是不可变的(一经设置便无法更改)。Cloud 控制台会自动生成一个唯一字符串;通常情况下,您无需关注该字符串。在大多数 Codelab 中,您都需要引用项目 ID(通常用
PROJECT_ID标识)。如果您不喜欢生成的 ID,可以再随机生成一个 ID。或者,您也可以尝试自己的项目 ID,看看是否可用。完成此步骤后便无法更改该 ID,并且此 ID 在项目期间会一直保留。 - 此外,还有第三个值,即部分 API 使用的项目编号,供您参考。如需详细了解所有这三个值,请参阅文档。
- 接下来,您需要在 Cloud 控制台中启用结算功能,以便使用 Cloud 资源/API。运行此 Codelab 应该不会产生太多的费用(如果有的话)。若要关闭资源以避免产生超出本教程范围的结算费用,您可以删除自己创建的资源或删除项目。Google Cloud 新用户符合参与 300 美元免费试用计划的条件。
激活 Cloud Shell
- 在 Cloud Console 中,点击激活 Cloud Shell
。

如果这是您第一次启动 Cloud Shell,系统会显示一个中间屏幕,说明它是什么。如果您看到中间屏幕,请点击继续。

预配和连接到 Cloud Shell 只需花几分钟时间。

这个虚拟机装有所需的所有开发工具。它提供了一个持久的 5 GB 主目录,并在 Google Cloud 中运行,大大增强了网络性能和身份验证功能。您在此 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`
- 在 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 Console 中,导航到菜单 ->Datastore(位于“Storage”部分)或点击此处。
如果您从未在当前项目中使用过 Datastore,则会看到“选择 Cloud Firestore 模式”屏幕。选择“Datastore 模式”选项。

然后,您会看到“选择数据的存储位置”屏幕。选择 us-east1 或任何其他地区位置,然后点击“创建数据库”:

4. 引导新的 Spring Boot Java 应用
在 CloudShell 环境中,使用以下命令初始化和启动新的 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 菜单中的打开编辑器,打开 Web 代码编辑器。

编辑器加载后,修改 pom.xml 文件以添加 Google Cloud Datastore 入门版和 Spring Shell 入门版依赖项:
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 数据库中的表,请参阅文档了解详情)。种类名称是可选的 - 如果省略它,系统将根据类名称生成种类名称。
请注意,我们为 id 属性添加了 @Id 注解。这表示我们希望将此字段用作 Datastore 键的标识符部分。每个 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 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 是网域类,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. 运行应用
要构建并启动应用,首先要确保将 JAVA_HOME 设置为正确的版本:
$ export JAVA_HOME=/usr/lib/jvm/java-1.17.0-openjdk-amd64
在 Cloud Shell 中(从 pom.xml 所在的项目 datastore-example/ 的根目录)执行此命令:
$ ./mvnw spring-boot:run export JAVA_HOME=/usr/lib/jvm/java-1.17.0-openjdk-amd64
构建阶段成功后,系统将显示 Spring 徽标并显示 Shell 提示:
. ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: 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>
请尝试以下操作:
- 使用
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 Console。输入“books”(如有必要)。

10. 清理
如需进行清理,请从 App Shell 中使用适当命名的 remove-all-books 命令移除所有图书。
shell:> remove-all-books
如需退出应用,请使用 quit 命令,然后按 Ctrl+C。
11. 恭喜!
在此 Codelab 中,您创建了一个交互式 CLI 应用,该应用可以在 Cloud Datastore 中存储和检索对象!
了解详情
- Cloud Datastore:https://cloud.google.com/datastore/
- Spring Shell:https://projects.spring.io/spring-shell/
- GCP 项目的 Spring:https://spring.io/projects/spring-cloud-gcp
- GCP GitHub 代码库上的 Spring:https://github.com/GoogleCloudPlatform/spring-cloud-gcp
- Google Cloud Platform 上的 Java:https://cloud.google.com/java/
许可
此作品已获得 Creative Commons Attribution 2.0 通用许可授权。