编辑此页面

您的第二个 Quarkus 应用程序

本教程将展示如何创建一个应用程序,该应用程序可以写入和读取数据库。 你将使用 Dev Services,因此你实际上无需自己下载、配置甚至启动数据库。 你还将使用 Panache (Hibernate ORM 之上的一个层),以简化数据的读取和写入。

本指南可以帮助你:

  • 向数据库读取和写入对象

  • 以零配置开发和测试服务

先决条件

要完成本指南,您需要

  • 大约 30 分钟

  • 一个 IDE

  • 已安装 JDK 17+ 并正确配置了 JAVA_HOME

  • Apache Maven 3.9.9

  • 一个正常工作的容器运行时(Docker 或 Podman

  • 如果您想使用它,可以选择 Quarkus CLI

本教程建立在你学习编写第一个 Quarkus 应用程序的基础上。 你将不需要该应用程序的代码,但请确保你理解了这些概念。

解决方案

我们建议你按照从引导项目开始的说明逐步创建应用程序。

但是,你可以直接转到完成的示例。

下载存档文件或克隆 git 仓库

git clone https://github.com/quarkusio/quarkus-quickstarts.git

解决方案位于 getting-started-dev-services 目录中。

1. 步骤概要

  • 引导应用程序

  • 更新应用程序以读取用户输入

  • 创建 Panache 实体

  • 读取和写入实体

  • 使用配置文件配置外部数据库

2. 设置交互式应用程序

2.1. 引导项目

创建新 Quarkus 项目的最简单方法是打开终端并运行以下命令

CLI
quarkus create app org.acme:getting-started-dev-services \
    --extension='rest'
cd getting-started-dev-services

要创建 Gradle 项目,请添加 --gradle--gradle-kotlin-dsl 选项。

有关如何安装和使用 Quarkus CLI 的更多信息,请参阅 Quarkus CLI 指南。

Maven
mvn io.quarkus.platform:quarkus-maven-plugin:3.24.4:create \
    -DprojectGroupId=org.acme \
    -DprojectArtifactId=getting-started-dev-services \
    -Dextensions='rest'
cd getting-started-dev-services

要创建 Gradle 项目,请添加 -DbuildTool=gradle-DbuildTool=gradle-kotlin-dsl 选项。

对于 Windows 用户

  • 如果使用 cmd,(不要使用反斜杠 \ 并将所有内容放在同一行上)

  • 如果使用 Powershell,请将 -D 参数括在双引号中,例如 "-DprojectArtifactId=getting-started-dev-services"

有关生成的应用程序内容的说明,请参阅第一个应用程序指南

2.2. 运行应用程序

在开发模式下启动应用程序

CLI
quarkus dev
Maven
./mvnw quarkus:dev
Gradle
./gradlew --console=plain quarkusDev

应用程序启动后,访问https://:8080/hello。 它应该显示“Hello from Quarkus REST”消息。

2.3. 接受用户输入

让我们让应用程序更具交互性。 在你的 IDE 中打开项目,然后导航到 src/main/java/org/acme/GreetingResource.javahello 方法中添加一个查询参数。(org.jboss.resteasy.reactive.RestQuery 注释类似于 Jakarta REST @QueryParam 注释,只不过你不需要重复参数名称。)

public String hello(@RestQuery String name) {
    return "Hello " + name;
}

你应该看到一条个性化消息:Hello Bloom

2.4. 修复测试

在你的 Quarkus 终端中,键入“r”来运行测试。 你应该看到你的应用程序更改破坏了测试!

要修复测试,请打开 src/test/java/org/acme/GreetingResourceTest.java 并替换

             .body(is("Hello from Quarkus REST"));

使用

             .body(containsString("Hello"));

这仍然验证了 HTTP 端点,但它对预期输出更加灵活。 你应该在终端中看到测试现在正在通过。

3. 添加持久性

3.1. 创建 Panache 实体

  1. 要添加持久性库,请运行

CLI
quarkus extension add hibernate-orm-panache,jdbc-postgresql
Maven
./mvnw quarkus:add-extension -Dextensions='hibernate-orm-panache,jdbc-postgresql'
Gradle
./gradlew addExtension --extensions='hibernate-orm-panache,jdbc-postgresql'

应用程序将记录它问候的人的姓名。 通过创建 Greeting.java 类来定义一个实体。 添加以下内容

import io.quarkus.hibernate.orm.panache.PanacheEntity;
import jakarta.persistence.Entity;

@Entity
public class Greeting extends PanacheEntity {
    public String name;
}

该实体使用了 Panache,它是 Hibernate ORM 之上的一个层。 扩展 PanacheEntity 会引入一系列用于读取、写入和查找数据的方法。 因为所有数据访问方法都在 Greeting 实体上,而不是在单独的数据访问类上,所以这是活动记录模式的一个示例。

Greeting 表将有一列,一个名为 name 的字段。

3.2. 写入数据

要使用新实体,请更新 hello 方法以开始写入一些数据。

将方法更改为以下内容

@GET
@Transactional
@Produces(MediaType.TEXT_PLAIN)
public String hello(@QueryParam("name") String name) {
   Greeting greeting = new Greeting();
   greeting.name = name;
   greeting.persist();
   return "Hello " + name;
}

不要忘记 @Transactional 注释,它确保写入操作被包装在一个事务中。

GET 请求不应更改应用程序状态。
通常,你不应该在 GET REST 方法中执行状态更新,但在这里它使尝试各种操作变得更简单。 让我们假设正在写入的内容是日志记录“副作用”,而不是有意义的状态更改!

通过访问 https://:8080/hello?name=Bloom 来试用更新后的端点。 你应该看到“Hello Bloom”消息。

3.3. 读取数据

尽管新的持久性代码似乎运行良好,没有任何错误,但你如何知道任何内容正在被写入数据库?

GreetingResource 添加第二个 REST 方法。

@GET
@Path("names")
@Produces(MediaType.TEXT_PLAIN)
public String names() {
    List<Greeting> greetings = Greeting.listAll();
    String names = greetings.stream().map(g-> g.name)
       .collect(Collectors.joining (", "));
    return "I've said hello to " + names;
}

要尝试一下,请访问 https://:8080/hello?name=Bloom,然后访问 https://:8080/hello/names

你应该看到以下消息:“I’ve said hello to Bloom”。

需要一个容器运行时。

不要忘记你需要有一个可用的容器运行时,否则你会在 Quarkus 日志中开始看到故障。

4. 开发服务

读取和写入数据库似乎运行良好,但这有点出乎意料。 PostgreSQL 数据库从哪里来的? 你没有设置任何内容。

数据库正在使用 Dev Services 进行管理。 Dev Services 负责停止和启动你的应用程序所需的服务。 因为你包含了 jdbc-postgresql 依赖项,所以数据库是一个容器化的 PostgreSQL 数据库。 如果你添加了 jdbc-mysql,你将获得一个容器化的 MySQL 数据库。

如果你愿意,可以使用你的容器工具来查看正在运行的容器。 例如,如果你正在使用 Docker,请运行 docker ps,对于 podman,请运行 podman ps。 你应该看到如下内容

ff88dcedd899  docker.io/library/postgres:14  postgres -c fsync...  20 minutes ago  Up 20 minutes  0.0.0.0:34789->5432/tcp  nostalgic_bassi

停止 Quarkus 并再次运行 docker ps。 你应该看到没有任何内容在运行(容器可能需要一些时间才能关闭)。 当你的应用程序停止时,Quarkus 将自动停止容器。

4.1. 初始化服务

如果你进一步研究你的代码,你可能会注意到,有时在进行应用程序更改后,https://:8080/hello/names 不会列出任何名称。 发生了什么? 默认情况下,在开发模式下,使用 Dev Services 数据库,Quarkus 将 Hibernate ORM 数据库模式管理策略配置为 drop-and-create。 有关更多详细信息,请参阅 Hibernate 配置参考。 如果代码更改触发应用程序重新启动,数据库表将被删除,然后重新创建。

这很方便,但是如果你希望数据库始终具有内容怎么办? 这会使测试更容易。 如果你提供一个 import.sql 文件,Quarkus 将使用它在每次启动时初始化数据库。

  1. 在你的项目中创建一个 src/main/resources/import.sql 文件

  2. 添加以下 SQL 语句

INSERT INTO Greeting(id, name)
VALUES (nextval('Greeting_SEQ'), 'Alice');
INSERT INTO Greeting(id, name)
VALUES (nextval('Greeting_SEQ'), 'Bob');

现在,在你的开发模式会话中按 s,强制完全重新启动。 然后访问 https://:8080/hello/names

你会看到 Alice 和 Bob 始终包含在名称列表中。

5. 控制开发服务

5.1. 改用外部数据库

如果你更喜欢使用自己管理的外部数据库怎么办? 将以下内容添加到 src/main/resources/application.properties

# configure your datasource
quarkus.datasource.db-kind = postgresql
quarkus.datasource.username = leopold
quarkus.datasource.password = bloom
quarkus.datasource.jdbc.url = jdbc:postgresql://:5432/mydatabase

这告诉 Quarkus 你不希望它启动 Dev Service,因为你有自己的数据库。 你无需担心启动数据库,因为你只是在了解如何更改配置。

访问 https://:8080/hello/names。 你将得到一个红色错误屏幕,而不是名称列表。 在 Quarkus 运行的终端中,你将看到以下堆栈错误消息

2023-06-28 19:18:22,880 ERROR [io.qua.ver.htt.run.QuarkusErrorHandler] (executor-thread-1) HTTP Request to /hello?name=fred failed, error id: 4f9b5ce6-3b08-41c5-af36-24eee4d1dd2b-2: org.hibernate.exception.JDBCConnectionException: Unable to acquire JDBC Connection [Connection to localhost:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.] [n/a]
        at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:98)
        at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:56)
...

这是有道理的;你已经禁用了数据库 Dev Service,但你没有启动自己的数据库。

5.2. 使用配置文件

除非你愿意,否则不要担心设置外部数据库来解决连接错误。 相反,你将返回使用 Dev Service。 它使生活变得轻松!

但是生产环境呢? 你不会希望在生产环境中使用 Dev Services。 事实上,Quarkus 只会在开发和测试模式下启动 Dev Services。

如果可以配置一个外部数据库,但在生产环境中使用,以便你仍然可以在其他时间使用 Dev Services,那不是很好吗?

在数据库配置中添加 %prod. 前缀。 这意味着配置仅适用于 prod 配置文件

配置应如下所示

# configure your datasource
%prod.quarkus.datasource.db-kind = postgresql
%prod.quarkus.datasource.username = leopold
%prod.quarkus.datasource.password = bloom
%prod.quarkus.datasource.jdbc.url = jdbc:postgresql://:5432/mydatabase

现在,外部数据库将在生产模式下使用,而 Dev Services 将在开发和测试模式下使用。

检查 https://:8080/hello/names。 它应该再次工作,因为 Dev Services 已重新启用。 请注意,对于这些更改,无需重新启动 Quarkus。

总结

你已经采用了一个简单的 REST 应用程序,并将其更新为从数据库写入和读取数据,使用 Hibernate ORM 和 Panache。 数据被持久化到“真实”数据库,而你无需配置任何内容。

相关内容