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 通用许可授权。