Using Hibernate Reactive
Hibernate Reactive 是面向 Hibernate ORM 的反应式 API,支持非阻塞数据库驱动程序以及与数据库进行反应式交互的样式。
Hibernate Reactive is a reactive API for Hibernate ORM, supporting non-blocking database drivers and a reactive style of interaction with the database.
Hibernate Reactive 并不是 Hibernate ORM 或 Hibernate ORM 的未来替代品。它是一个不同的堆栈,专为需要高并发性的反应式用例而定制。 Hibernate Reactive is not a replacement for Hibernate ORM or the future of Hibernate ORM. It is a different stack tailored for reactive use cases where you need high-concurrency. 此外,使用 Quarkus REST(以前称为 RESTEasy Reactive),我们的默认 REST 层,不需要使用 Hibernate Reactive。使用 Quarkus REST 搭配 Hibernate ORM 是完全有效的,如果你不需要高并发性,也不熟悉反应式范例,则建议使用 Hibernate ORM。 Also, using Quarkus REST (formerly RESTEasy Reactive), our default REST layer, does not require the use of Hibernate Reactive. It is perfectly valid to use Quarkus REST with Hibernate ORM, and if you do not need high-concurrency, or are not accustomed to the reactive paradigm, it is recommended to use Hibernate ORM. |
Hibernate Reactive 使用了与Hibernate ORM guide中描述的大部分配置相同的注释。本指南将仅关注与 Hibernate Reactive 特有的内容。 Hibernate Reactive works with the same annotations and most of the configuration described in the Hibernate ORM guide. This guide will only focus on what’s specific for Hibernate Reactive. |
Unresolved directive in hibernate-reactive.adoc - include::{includes}/extension-status.adoc[]
Solution
我们建议您遵循接下来的部分中的说明,按部就班地创建应用程序。然而,您可以直接跳到完成的示例。
We recommend that you follow the instructions in the next sections and create the application step by step. However, you can go right to the completed example.
克隆 Git 存储库: git clone {quickstarts-clone-url}
,或下载 {quickstarts-archive-url}[存档]。
Clone the Git repository: git clone {quickstarts-clone-url}
, or download an {quickstarts-archive-url}[archive].
解决方案位于 hibernate-reactive-quickstart
directory。
The solution is located in the hibernate-reactive-quickstart
directory.
Setting up and configuring Hibernate Reactive
在 Quarkus 中使用 Hibernate Reactive 时,您需要:
When using Hibernate Reactive in Quarkus, you need to:
-
add your configuration settings in
application.properties
-
annotate your entities with
@Entity
and any other mapping annotations as usual
自动执行其他配置需求:Quarkus 将做出一些主观的选项和有根据的猜测。
Other configuration needs have been automated: Quarkus will make some opinionated choices and educated guesses.
添加以下依赖关系到您的项目:
Add the following dependencies to your project:
-
the Hibernate Reactive extension:
io.quarkus:quarkus-hibernate-reactive
-
the Reactive SQL client extension for the database of your choice; the following options are available:
-
quarkus-reactive-pg-client
: the client for PostgreSQL or CockroachDB -
quarkus-reactive-mysql-client
: the client MySQL or MariaDB -
quarkus-reactive-mssql-client
: the client for Microsoft SQL Server -
quarkus-reactive-db2-client
: the client for IBM Db2 -
quarkus-reactive-oracle-client
: the client for Oracle
-
例如:
For instance:
<!-- 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
中添加相关的配置属性:
Annotate your persistent objects with @Entity
,
then add the relevant configuration properties in 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://localhost/quarkus_test 1
# drop and create the database at startup (use `update` to only update the schema)
quarkus.hibernate-orm.database.generation=drop-and-create
1 | The only different property from a Hibernate ORM configuration |
请注意,这些配置属性与典型的 Hibernate Reactive 配置文件中不同。它们经常会映射到 Hibernate Reactive 配置属性,但可能有不同的名称,并且不一定相互一一映射。
Note that these configuration properties are not the same ones as in your typical Hibernate Reactive configuration file. They will often map to Hibernate Reactive configuration properties but could have different names and don’t necessarily map 1:1 to each other.
另外,Quarkus 会自动设置许多 Hibernate Reactive 配置设置,而且通常使用较新版本的默认值。
Also, Quarkus will set many Hibernate Reactive configuration settings automatically, and will often use more modern defaults.
无法使用标准 persistence.xml
配置文件配置 Hibernate Reactive。
Configuring Hibernate Reactive using the standard persistence.xml
configuration file is not supported.
请参阅 Hibernate Reactive configuration properties 部分以了解可以在 application.properties
中设置的属性列表。
See section hr-configuration-properties for the list of properties you can set in application.properties
.
只要 Hibernate Reactive 扩展列在项目依赖项中,就会根据 Quarkus datasource
配置创建一个 Mutiny.SessionFactory
。
A Mutiny.SessionFactory
will be created based on the Quarkus datasource
configuration as long as the Hibernate Reactive extension is listed among your project dependencies.
方言将根据 Reactive SQL 客户端选择 - 除非您明确设置了一个方言。
The dialect will be selected based on the Reactive SQL client - unless you set one explicitly.
然后,您可以愉快地注入您的 Mutiny.SessionFactory
:
You can then happily inject your 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 | Inject your session factory and have fun |
2 | .withTransaction() will automatically flush at commit |
请务必在事务中包装修改数据库的方法(例如 session.persist(entity)
)。
Make sure to wrap methods modifying your database (e.g. session.persist(entity)
) within a transaction.
@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 语句。请务必用分号终止每个语句。
To load SQL statements when Hibernate Reactive starts, add an import.sql
file in your src/main/resources/
directory.
This script can contain any SQL DML statements.
Make sure to terminate each statement with a semicolon.
这可用于为测试或演示准备好数据集。
This is useful to have a data set ready for your tests or demos.
Hibernate Reactive configuration properties
有各种可选属性可用于改进会话工厂或指导 Quarkus 猜测。
There are various optional properties useful to refine your session factory or guide Quarkus' guesses.
如果没有设置任何属性,Quarkus 通常可以推断出它设置 Hibernate Reactive 所需的一切,并且会让它使用默认数据源。
When no properties are set, Quarkus can typically infer everything it needs to set up Hibernate Reactive and will have it use the default datasource.
此处列出的配置属性允许您覆盖这些默认值,并自定义和调整各个方面。
The configuration properties listed here allow you to override such defaults, and customize and tune various aspects.
Hibernate Reactive 使用您在 Hibernate ORM 中使用的相同属性。您会注意到某些属性在名称中包含 jdbc
但 Hibernate Reactive 中没有 JDBC,这些只是旧版属性名。
Hibernate Reactive uses the same properties you would use for Hibernate ORM. You will notice that some properties
contain jdbc
in the name but there is no JDBC in Hibernate Reactive, these are simply legacy property names.
Unresolved directive in hibernate-reactive.adoc - include::{generated-dir}/config/quarkus-hibernate-orm.adoc[]
想在 Docker 中启动 PostgreSQL 服务器吗? Want to start a PostgreSQL server on the side with Docker?
这将启动一个非持久性的空数据库:非常适合快速实验! This will start a non-durable empty database: ideal for a quick experiment! |
CDI integration
如果您熟悉在 Quarkus 中使用 Hibernate Reactive,那么您可能已经使用 CDI 注入 Mutiny.SessionFactory
:
If you are familiar with using Hibernate Reactive in Quarkus, you probably already have injected the Mutiny.SessionFactory
using CDI:
@Inject
Mutiny.SessionFactory sessionFactory;
这会注入默认持久性单元的 Mutiny.SessionFactory
。
This will inject the Mutiny.SessionFactory
of the default persistence unit.
在 Quarkus 3.0 之前,还可以为 |
Prior to Quarkus 3.0 it was also possible to inject a |
Automatically transitioning to Flyway to Manage Schemas
Hibernate Reactive 可以在与 Flyway 相同的应用程序中使用。有关在响应式应用程序中配置 Flyway 的详细信息,请参阅 this section of the Flyway extension documentation。
Hibernate Reactive can be used in the same application as Flyway. See this section of the Flyway extension documentation for details regarding configuration of Flyway in a reactive application.
如果在开发模式下运行时安装了 Flyway extension,Quarkus 提供了一种简单的方法来使用 Hibernate Reactive 自动生成的模式初始化 Flyway 配置。 If you have the Flyway extension installed when running in development mode, Quarkus provides a simple way to initialize your Flyway configuration using the schema generated automatically by Hibernate Reactive. 查看 the Hibernate ORM guide 了解更多详情。 See the Hibernate ORM guide for more details. |
Testing
由于 API 的异步特性以及所有操作都需要在 Vert.x 事件循环上运行,所以在 @QuarkusTest
中使用 Hibernate Reactive 比使用 Hibernate ORM 稍微复杂一些。
Using Hibernate Reactive in a @QuarkusTest
is slightly more involved than using Hibernate ORM due to the asynchronous nature of the APIs and the fact that all operations need to run on a Vert.x Event Loop.
编写这些测试需要两个组件:
Two components are necessary to write these tests:
-
The use of
@io.quarkus.test.vertx.RunOnVertxContext
or@io.quarkus.test.TestReactiveTransaction
on the test methods -
The use of
io.quarkus.test.vertx.UniAsserter
as a test method parameter.
这些类由 quarkus-test-vertx
依赖项提供。
These classes are provided by the quarkus-test-vertx
dependency.
一个非常简单的用例如下所示:
A very simple example usage looks like:
@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));
}
}
请参阅 |
See the Javadoc of |
您还可以扩展 You can also extend the
|
Limitations and other things you should know
Quarkus 不会修改它使用的库;此规则也适用于 Hibernate Reactive:使用此扩展时,您几乎会与使用原始库有相同的操作体验。
Quarkus does not modify the libraries it uses; this rule applies to Hibernate Reactive as well: when using this extension you will mostly have the same experience as using the original library.
但是,当它们共享相同的代码时,Quarkus 会自动配置某些组件并注入某些扩展点的自定义实现;这应该是透明且有用的,但如果您是 Hibernate Reactive 专家,您可能想要了解正在做什么。
But while they share the same code, Quarkus does configure some components automatically and inject custom implementations for some extension points; this should be transparent and useful but if you’re an expert of Hibernate Reactive you might want to know what is being done.
以下是在 Quarkus 中使用 Hibernate Reactive 时需要注意的事项列表:
Here’s a list of things to pay attention when using Hibernate Reactive in Quarkus:
-
Hibernate Reactive is not configurable via a
persistence.xml
file. -
This extension only considers the default persistence unit at the moment: it’s not possible to configure multiple persistence units, or even a single named persistence unit.
-
This extension cannot be used at the same time as Hibernate ORM. See [role="bare"]https://github.com/quarkusio/quarkus/issues/13425.
-
Integration with the Envers extension is not supported.
-
Transaction demarcation cannot be done using
jakarta.transaction.Transactional
orQuarkusTransaction
; if you use Hibernate Reactive with Panache, consider using@WithTransaction
orPanache.withTransaction()
instead.
Simplifying Hibernate Reactive with Panache
Hibernate Reactive with Panache扩展通过提供活动记录样式实体(和存储库)来促进 Hibernate Reactive 的使用,专注于让编写您的实体变得轻松且有趣。
The Hibernate Reactive with Panache extension facilitates the usage of Hibernate Reactive by providing active record style entities (and repositories) and focuses on making your entities trivial and fun to write in Quarkus.