使用 Hibernate Reactive
Hibernate Reactive 是 Hibernate ORM 的一个响应式 API,支持非阻塞数据库驱动程序和与数据库进行响应式风格的交互。
Hibernate Reactive 不是 Hibernate ORM 的替代品,也不是 Hibernate ORM 的未来。它是一个为响应式用例量身定制的不同堆栈,在这些用例中您需要高并发性。 此外,使用 Quarkus REST(以前的 RESTEasy Reactive),我们的默认 REST 层,不需要使用 Hibernate Reactive。将 Quarkus REST 与 Hibernate ORM 一起使用是完全有效的,如果您不需要高并发性,或者不习惯响应式范例,建议使用 Hibernate ORM。 |
Hibernate Reactive 使用与 Hibernate ORM 指南中描述的相同的注解和大多数配置。本指南将只关注 Hibernate Reactive 特有的内容。 |
此技术被认为是预览版。 在预览中,不保证向后兼容性和在生态系统中的存在。具体的改进可能需要更改配置或 API,成为稳定版的计划正在进行中。欢迎通过我们的 邮件列表 或在我们的 GitHub 问题跟踪器 中提供反馈。 有关可能的完整状态列表,请查看我们的常见问题解答条目。 |
解决方案
我们建议您按照以下章节中的说明,逐步创建应用程序。但是,您可以直接转到完整的示例。
克隆 Git 仓库:git clone https://github.com/quarkusio/quarkus-quickstarts.git
,或下载 归档文件。
解决方案位于 hibernate-reactive-quickstart
目录中。
设置和配置 Hibernate Reactive
在 Quarkus 中使用 Hibernate Reactive 时,您需要
-
在
application.properties
中添加您的配置设置 -
像往常一样使用
@Entity
和任何其他映射注解来注解您的实体
其他配置需求已经自动化:Quarkus 将做出一些主观选择和有根据的猜测。
将以下依赖项添加到您的项目
-
Hibernate Reactive 扩展:
io.quarkus:quarkus-hibernate-reactive
-
您选择的数据库的 响应式 SQL 客户端扩展;以下选项可用
-
quarkus-reactive-pg-client
:PostgreSQL 或 CockroachDB 的客户端 -
quarkus-reactive-mysql-client
:MySQL 或 MariaDB 的客户端 -
quarkus-reactive-mssql-client
:Microsoft SQL Server 的客户端 -
quarkus-reactive-db2-client
:IBM Db2 的客户端 -
quarkus-reactive-oracle-client
:Oracle 的客户端
-
例如
<!-- Hibernate Reactive dependency -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-hibernate-reactive</artifactId>
</dependency>
<!-- Reactive SQL client for PostgreSQL -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-reactive-pg-client</artifactId>
</dependency>
// Hibernate Reactive dependency
implementation("io.quarkus:quarkus-hibernate-reactive")
Reactive SQL client for PostgreSQL
implementation("io.quarkus:quarkus-reactive-pg-client")
使用 @Entity
注解您的持久对象,然后在 application.properties
中添加相关的配置属性
application.properties
示例# datasource configuration
quarkus.datasource.db-kind = postgresql
quarkus.datasource.username = quarkus_test
quarkus.datasource.password = quarkus_test
quarkus.datasource.reactive.url = vertx-reactive:postgresql:///quarkus_test (1)
# drop and create the database at startup (use `update` to only update the schema)
quarkus.hibernate-orm.schema-management.strategy=drop-and-create
1 | 与 Hibernate ORM 配置唯一不同的属性 |
请注意,这些配置属性与您典型的 Hibernate Reactive 配置文件中的配置属性不同。它们通常会映射到 Hibernate Reactive 配置属性,但可能具有不同的名称,并且不一定彼此 1:1 映射。
阻塞(非响应式)和响应式配置可以在同一个项目中混合使用。
不支持使用标准的 persistence.xml 配置文件配置 Hibernate Reactive。 |
有关您可以在 application.properties
中设置的属性列表,请参阅 Hibernate Reactive 配置属性 部分。
只要 Hibernate Reactive 扩展在您的项目依赖项中列出,就会基于 Quarkus datasource
配置创建一个 Mutiny.SessionFactory
。
方言将根据响应式 SQL 客户端进行选择 - 除非您显式设置一个。
然后您可以愉快地注入您的 Mutiny.SessionFactory
@ApplicationScoped
public class SantaClausService {
@Inject
Mutiny.SessionFactory sf; (1)
public Uni<Void> createGift(String giftDescription) {
Gift gift = new Gift();
gift.setName(giftDescription);
return sf.withTransaction(session -> session.persist(gift)) (2)
}
}
1 | 注入您的会话工厂并享受乐趣 |
2 | .withTransaction() 将在提交时自动刷新 |
确保将修改数据库的方法(例如 session.persist(entity) )包装在事务中。 |
@Entity
public class Gift {
private Long id;
private String name;
@Id
@SequenceGenerator(name = "giftSeq", sequenceName = "gift_id_seq", allocationSize = 1, initialValue = 1)
@GeneratedValue(generator = "giftSeq")
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
要在 Hibernate Reactive 启动时加载 SQL 语句,请在您的 src/main/resources/
目录中添加一个 import.sql
文件。此脚本可以包含任何 SQL DML 语句。确保以分号结束每个语句。
这对于准备好用于测试或演示的数据集很有用。
Hibernate Reactive 配置属性
有各种可选属性可用于完善您的会话工厂或指导 Quarkus 的猜测。
当未设置任何属性时,Quarkus 通常可以推断出设置 Hibernate Reactive 所需的一切,并将使其使用默认数据源。
此处列出的配置属性允许您覆盖此类默认值,并自定义和调整各个方面。
Hibernate Reactive 使用与 Hibernate ORM 相同的属性。您会注意到某些属性的名称中包含 jdbc
,但 Hibernate Reactive 中没有 JDBC,这些只是遗留属性名称。
构建时固定的配置属性 - 所有其他配置属性都可以在运行时覆盖
配置属性 |
类型 |
默认 |
||
---|---|---|---|---|
在构建期间是否启用 Hibernate ORM。 如果在构建期间禁用 Hibernate ORM,则将跳过与 Hibernate ORM 相关的所有处理,但无法在运行时激活 Hibernate ORM: 环境变量: 显示更多 |
布尔值 |
|
||
Hibernate ORM 是否以阻塞模式工作。 如果未找到 JDBC 数据源,Hibernate ORM 的阻塞 环境变量: 显示更多 |
布尔值 |
|
||
如果为 环境变量: 显示更多 |
布尔值 |
|
||
是否启用统计信息收集。如果“metrics.enabled”为 true,则此处默认值被认为是 true,否则默认值为 false。 环境变量: 显示更多 |
布尔值 |
|||
是否应将会话指标附加到服务器日志中,用于每个 Hibernate 会话。这仅在启用统计信息时有效 ( 环境变量: 显示更多 |
布尔值 |
|||
如果启用了指标扩展,是否发布指标。 环境变量: 显示更多 |
布尔值 |
|
||
允许在 Dev UI 页面中使用 hql 查询 环境变量: 显示更多 |
布尔值 |
|
||
当没有活动事务但请求范围有效时,启用或禁用对 Hibernate ORM 环境变量: 显示更多 |
布尔值 |
|
||
此持久化单元使用的数据源的名称。 如果未定义,它将使用默认数据源。 环境变量: 显示更多 |
字符串 |
|||
受此持久化单元影响的实体所在的包。 环境变量: 显示更多 |
字符串列表 |
|||
包含在 Hibernate ORM 启动时执行的 SQL 语句的文件的路径。 这些文件是从类路径资源中检索的,因此它们必须位于 resources 目录中(例如 此设置的默认值取决于 Quarkus 启动模式
如果您需要在开发模式、测试 ( application.properties
环境变量: 显示更多 |
字符串列表 |
|
||
用于应用数据库对象名称的物理命名规则的可插拔策略合同。 Hibernate PhysicalNamingStrategy 实现的类名 环境变量: 显示更多 |
字符串 |
|||
在未给出显式名称时,用于应用隐式命名规则的可插拔策略。 Hibernate ImplicitNamingStrategy 实现的类名 环境变量: 显示更多 |
字符串 |
|||
环境变量: 显示更多 |
字符串 |
|||
用于配置实体映射的 XML 文件,例如 如果存在,则默认为 环境变量: 显示更多 |
字符串列表 |
|
||
可以使用可用的策略之一来引用标识符。 默认设置为 环境变量: 显示更多 |
|
|
||
Quarkus 中的默认设置为启用 2 级缓存,并且已经为您集成了一个良好的实现。 只需挑出哪些实体应使用缓存。 将此设置为 false 以禁用所有 2 级缓存。 环境变量: 显示更多 |
布尔值 |
|
||
定义 Bean Validation 集成的行为方式。 环境变量: 显示更多 |
|
|
||
定义多租户的方法(DATABASE、NONE、SCHEMA)。 允许值的完整列表可在 Hibernate ORM JavaDoc 中找到。 当前不支持 DISCRIMINATOR 类型。 默认值为 NONE(无多租户)。 环境变量: 显示更多 |
字符串 |
|||
如果 Hibernate 没有自动生成架构,并且 Quarkus 在开发模式下运行,则 Quarkus 将尝试在启动后验证数据库,并在出现任何问题时打印日志消息。 环境变量: 显示更多 |
布尔值 |
|
||
此持久化单元是否应在运行时处于活动状态。 请参阅 文档的此部分。 请注意,如果禁用了 Hibernate ORM(即 环境变量: 显示更多 |
布尔值 |
|
||
应直接传递给 Hibernate ORM 的属性。 在此处使用完整的配置属性键,例如
考虑在使用不受支持的配置属性之前使用受支持的配置属性。 如果不存在,请确保提交功能请求,以便可以将受支持的配置属性添加到 Quarkus,更重要的是,可以定期测试该配置属性。 环境变量: 显示更多 |
Map<String,String> |
|||
类型 |
默认 |
|||
设置后,尽最大努力尝试与给定版本的 Hibernate ORM 进行数据交换。 请注意
环境变量: 显示更多 |
|
|
||
数据库的字符集。 用于 DDL 生成和 SQL 导入脚本。 环境变量: 显示更多 |
|
|||
用于数据库对象的默认目录。 环境变量: 显示更多 |
字符串 |
|||
用于数据库对象的默认架构。 环境变量: 显示更多 |
字符串 |
|||
Hibernate ORM 是否应在启动时检查数据库的版本是否与方言上配置的版本匹配(默认版本或通过 如果数据库在启动时不可用,则应将此设置为 环境变量: 显示更多 |
布尔值 |
|
||
类型 |
默认 |
|||
Hibernate ORM 方言的名称。 对于 受支持的数据库,不需要显式设置此属性:它会根据数据源自动选择,并使用 在数据源上设置的 DB 版本进行配置,以从最佳性能和最新功能中受益。 如果您的数据库没有相应的 Quarkus 扩展,则需要显式设置此属性。 在这种情况下,请记住 JDBC 驱动程序和 Hibernate ORM 方言可能无法在 GraalVM 本机可执行文件中正常工作。 对于内置方言,预期值是 方言的官方列表中的名称之一,没有 对于第三方方言,预期值是完全限定的类名,例如 环境变量: 显示更多 |
字符串 |
|
||
当方言支持多个存储引擎时,要使用的存储引擎。 例如 MySQL 的 环境变量: 显示更多 |
字符串 |
|||
类型 |
默认 |
|||
默认情况下如何为 可以使用
环境变量: 显示更多 |
|
|
||
要应用于其优化器未显式配置的标识符生成器的优化器。 仅与基于表和序列的标识符生成器相关。 其他生成器(例如基于 UUID 的生成器)将忽略此设置。 优化器负责汇集新的标识符值,以减少数据库调用的频率来检索这些值,从而提高性能。 环境变量: 显示更多 |
|
|
||
类型 |
默认 |
|||
查询计划缓存的最大大小。 请参阅 # 环境变量: 显示更多 |
整数 |
|
||
有效值为: 环境变量: 显示更多 |
|
|
||
启用 IN 子句参数填充,这可以提高语句缓存。 环境变量: 显示更多 |
布尔值 |
|
||
当无法在数据库端应用限制时,触发异常,而不是尝试性能不佳的内存结果集限制。 当分页与应用于集合或多值关联的提取连接结合使用时,限制必须在内存中应用,而不是在数据库中应用。 应避免这种情况,因为它通常具有很差的性能特征。 环境变量: 显示更多 |
布尔值 |
|
||
类型 |
默认 |
|||
推送到 JDBC 驱动程序的时区。 请参阅 环境变量: 显示更多 |
字符串 |
|||
JDBC 驱动程序一次提取多少行。 环境变量: 显示更多 |
整数 |
|||
JDBC 驱动程序一次发送多少更新(插入、更新和删除)来执行。 环境变量: 显示更多 |
整数 |
|||
类型 |
默认 |
|||
加载实体和集合时使用的批次的大小。
环境变量: 显示更多 |
整数 |
|
||
单端关联(一对一,多对一)的外连接提取树的最大深度。
环境变量: 显示更多 |
整数 |
|||
类型 |
默认 |
|||
缓存对象被视为过期的最大时间。 环境变量: 显示更多 |
||||
缓存中内存中保存的最大对象数。 环境变量: 显示更多 |
long |
|||
类型 |
默认 |
|||
现有应用程序(隐式或显式地)依赖于 Hibernate 忽略连接继承层次结构上的任何 DiscriminatorColumn 声明。此设置允许这些应用程序保持遗留行为,即 DiscriminatorColumn 注解在与连接继承配对时被忽略。 环境变量: 显示更多 |
布尔值 |
|
||
类型 |
默认 |
|||
记录 SQL 绑定参数。 显然,不建议在生产环境中将其设置为 true。 环境变量: 显示更多 |
布尔值 |
|
||
显示 SQL 日志并很好地格式化它们。 显然,不建议在生产环境中将其设置为 true。 环境变量: 显示更多 |
布尔值 |
|
||
如果启用了 SQL 日志,则格式化 SQL 日志 环境变量: 显示更多 |
布尔值 |
|
||
如果启用了 SQL 日志,则高亮显示 SQL 日志 环境变量: 显示更多 |
布尔值 |
|
||
是否应该收集和记录 JDBC 警告。 环境变量: 显示更多 |
布尔值 |
|
||
如果设置,Hibernate 将记录执行时间超过指定毫秒数的查询。 环境变量: 显示更多 |
long |
|||
类型 |
默认 |
|||
选择是否生成数据库模式。
默认为“none”。 但是,如果 Dev Services 正在使用中,并且不存在其他管理模式的扩展,则该值将自动覆盖为“drop-and-create”。 可接受的值: 环境变量: 显示更多 |
字符串 |
|
||
如果 Hibernate ORM 应该自动创建模式(对于支持它们的数据库)。 环境变量: 显示更多 |
布尔值 |
|
||
在应用模式时,我们是否应该在第一个错误时停止。 环境变量: 显示更多 |
布尔值 |
|
||
类型 |
默认 |
|||
选择是否生成数据库模式 DDL 文件。可接受的值: 环境变量: 显示更多 |
字符串 |
|
||
应该在其中生成数据库创建 DDL 文件的文件名或 URL。 环境变量: 显示更多 |
字符串 |
|||
应该在其中生成数据库删除 DDL 文件的文件名或 URL。 环境变量: 显示更多 |
字符串 |
|||
类型 |
默认 |
|||
默认的刷新策略,或者在 Hibernate 会话中何时将实体刷新到数据库:每次查询之前,在提交时,…… 可以通过 有关详细信息,请参阅 环境变量: 显示更多 |
|
|
关于 Duration 格式
要写入持续时间值,请使用标准的 您还可以使用简化的格式,以数字开头
在其他情况下,简化格式将被转换为
|
想要在 Docker 中启动一个 PostgreSQL 服务器吗?
这将启动一个非持久性的空数据库:非常适合快速实验! |
Hibernate ORM 和 Reactive 扩展同时使用
如果您将 Hibernate ORM 和 Hibernate Reactive 扩展都添加到您的 Quarkus 应用程序中,它们可以在同一个项目中混合使用。
如果您的应用程序通常使用 Hibernate ORM(它是阻塞的),但您想尝试 Hibernate Reactive 以查看它是否更适合您的情况,这将非常有用。
通过添加第二个扩展,您可以在代码的另一部分中使用 Reactive API - 无需创建单独的应用程序。
Hibernate ORM 和 Hibernate Reactive 不会共享同一个持久化上下文,因此建议您在一个给定的方法中坚持使用其中一个。例如,在阻塞的 REST 端点中使用 Hibernate ORM,并在 Reactive REST 端点中使用 Hibernate Reactive。 |
-
要同时使用这两个扩展,请将这两个扩展添加到
pom.xml
文件<!-- Hibernate reactive --> <dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-hibernate-reactive</artifactId> </dependency> <dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-reactive-pg-client</artifactId> </dependency> <!-- Hibernate ORM --> <dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-jdbc-postgresql</artifactId> </dependency> <dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-hibernate-orm</artifactId> </dependency>
-
还要更新
applications.properties
文件
%prod.quarkus.datasource.reactive.url=postgresql:///your_database %prod.quarkus.datasource.jdbc.url=jdbc:postgresql://:5432/hibernate_orm_test
-
JDBC 驱动程序的存在将启用 Hibernate ORM。如果您想禁用它,并且只使用 Hibernate Reactive,您可以使用
quarkus.hibernate-orm.blocking=false
Quarkus 将自动设置许多 Hibernate Reactive 配置设置,并且通常会使用更现代的默认值。
自动转换为 Flyway 来管理模式
Hibernate Reactive 可以与 Flyway 在同一个应用程序中使用。有关在 Reactive 应用程序中配置 Flyway 的详细信息,请参阅 Flyway 扩展文档的此部分。
如果在开发模式下运行时安装了 Flyway 扩展,Quarkus 提供了一种使用 Hibernate Reactive 自动生成的模式来初始化 Flyway 配置的简单方法。 有关更多详细信息,请参阅 Hibernate ORM 指南。 |
测试
由于 API 的异步特性以及所有操作都需要在 Vert.x 事件循环上运行,因此在 @QuarkusTest
中使用 Hibernate Reactive 比使用 Hibernate ORM 稍微复杂一些。
编写这些测试需要两个组件
-
在测试方法上使用
@io.quarkus.test.vertx.RunOnVertxContext
或@io.quarkus.test.TestReactiveTransaction
-
使用
io.quarkus.test.vertx.UniAsserter
作为测试方法参数。
这些类由 quarkus-test-vertx 依赖项提供。 |
一个非常简单的用法示例如下
@QuarkusTest
public class SomeTest {
@Inject
Mutiny.SessionFactory sessionFactory;
@Test
@RunOnVertxContext
public void testQuery(UniAsserter asserter) {
asserter.assertThat(() -> sessionFactory.withSession(s -> s.createQuery(
"from Gift g where g.name = :name").setParameter("name", "Lego").getResultList()),
list -> org.junit.jupiter.api.Assertions.assertEquals(list.size(), 1));
}
}
有关可用于创建断言的各种方法的完整说明,请参阅 UniAsserter 的 Javadoc。 |
您还可以扩展
|
命名数据源
Hibernate Reactive 支持具有命名数据源
application.properties
示例# datasource configuration
quarkus.hibernate-orm.datasource = named-datasource
quarkus.datasource."named-datasource".db-kind" = postgresql
# drop and create the database at startup (use `update` to only update the schema)
%prod.quarkus.hibernate-orm.schema-management.strategy=drop-and-create
%prod.quarkus.datasource."named-datasource".reactive" = true
%prod.quarkus.datasource."named-datasource".username" = quarkus_test
%prod.quarkus.datasource."named-datasource".password" = quarkus_test
%prod.quarkus.datasource.reactive.url = vertx-reactive:postgresql:///quarkus_test (1)
使用命名数据源时,您需要将 quarkus.hibernate-orm.datasource
属性设置为数据源的名称。
限制和其他您应该知道的事情
Quarkus 不会修改它使用的库;此规则也适用于 Hibernate Reactive:使用此扩展时,您将获得与使用原始库时大致相同的体验。
但是,虽然它们共享相同的代码,但 Quarkus 会自动配置一些组件并为某些扩展点注入自定义实现;这应该是透明且有用的,但如果您是 Hibernate Reactive 的专家,您可能想知道正在做什么。
以下是在 Quarkus 中使用 Hibernate Reactive 时需要注意的事项列表
-
Hibernate Reactive 不能通过
persistence.xml
文件进行配置。 -
此扩展目前仅考虑默认持久化单元:无法配置多个持久化单元,甚至无法配置单个命名持久化单元。
-
此扩展目前不支持 基于数据库的多租户 或 基于模式的多租户。另一方面,预计 基于鉴别器的多租户 可以正常工作。请参阅 https://github.com/quarkusio/quarkus/issues/15959。
-
不支持与 Envers 扩展集成。
-
事务划分不能使用
jakarta.transaction.Transactional
或QuarkusTransaction
完成;如果您使用 带有 Panache 的 Hibernate Reactive,请考虑 使用@WithTransaction
或Panache.withTransaction()
。
使用 Panache 简化 Hibernate Reactive
带有 Panache 的 Hibernate Reactive 扩展通过提供活动记录风格的实体(和存储库)来促进 Hibernate Reactive 的使用,并专注于使您在 Quarkus 中编写实体变得微不足道且有趣。
验证模式和 Hibernate Validator 集成
要了解更多关于 quarkus.hibernate-orm.validation.mode
配置属性如何影响您的 Hibernate Reactive 应用程序,请参阅 相应的 Hibernate ORM 指南,因为这些模式在两种情况下都以相同的方式工作。