Reactive SQL Clients
Reactive SQL 客户端具有直接的 API,重点是可扩展性和低开销。目前支持以下数据库服务器:
-
IBM Db2
-
PostgreSQL
-
MariaDB/MySQL
-
Microsoft SQL Server
-
Oracle
Oracle 的 Reactive SQL 客户端被认为是 tech preview。 在 tech preview 模式下,需要及早反馈来完善该理念。在解决方案成熟之前,平台的稳定性无法得到保证。欢迎在我们的 mailing list 或我们的 GitHub issue tracker 中作为问题提供反馈。 |
在本指南中,你将学习如何实现一个简单的 CRUD 应用程序,通过 RESTful API 公开存储在 PostgreSQL 中的数据。
可以在本文档的底部找到每个客户端的扩展名和连接池类名。 |
如果你不熟悉 Quarkus Vert.x 扩展,请考虑先阅读 Using Eclipse Vert.x 指南。
该应用程序应管理水果实体:
package org.acme.reactive.crud;
import io.smallrye.mutiny.Multi;
import io.smallrye.mutiny.Uni;
import io.vertx.mutiny.pgclient.PgPool;
import io.vertx.mutiny.sqlclient.Row;
import io.vertx.mutiny.sqlclient.RowSet;
import io.vertx.mutiny.sqlclient.Tuple;
public class Fruit {
public Long id;
public String name;
public Fruit() {
// default constructor.
}
public Fruit(String name) {
this.name = name;
}
public Fruit(Long id, String name) {
this.id = id;
this.name = name;
}
}
- Prerequisites
- Solution
- Installing
- Configuring
- Database schema and seed data
- Using
- Database Clients details
- Transactions
- Working with batch query results
- Multiple Datasources
- UNIX Domain Socket connections
- Load-balancing connections
- Pooled connection
idle-timeout
- Pooled Connection
max-lifetime
- Customizing pool creation
- Pipelining
- Configuration Reference
Prerequisites
如要完成本指南,您需要:
-
Roughly 15 minutes
-
An IDE
-
安装了 JDK 17+,已正确配置
JAVA_HOME
-
Apache Maven ${proposed-maven-version}
-
如果你想使用 Quarkus CLI, 则可以选择使用
-
如果你想构建一个本机可执行文件(或如果你使用本机容器构建,则使用 Docker),则可以选择安装 Mandrel 或 GraalVM 以及 configured appropriately
如果你在开发模式下启动应用程序,Quarkus 会开箱即用地为你提供一个 zero-config database。 你还可以预先启动一个数据库:
|
Solution
我们建议您遵循接下来的部分中的说明,按部就班地创建应用程序。然而,您可以直接跳到完成的示例。
克隆 Git 存储库: git clone $${quickstarts-base-url}.git
,或下载 $${quickstarts-base-url}/archive/main.zip[存档]。
此解决方案位于 getting-started-reactive-crud
directory。
Installing
Reactive PostgreSQL Client extension
首先,确保你的项目已启用 quarkus-reactive-pg-client
扩展。如果你正在创建一个新项目,请使用以下命令:
quarkus create app {create-app-group-id}:{create-app-artifact-id} \
--no-code
cd {create-app-artifact-id}
要创建一个 Gradle 项目,添加 --gradle
或 --gradle-kotlin-dsl
选项。
有关如何安装和使用 Quarkus CLI 的详细信息,请参见 Quarkus CLI 指南。
mvn {quarkus-platform-groupid}:quarkus-maven-plugin:{quarkus-version}:create \
-DprojectGroupId={create-app-group-id} \
-DprojectArtifactId={create-app-artifact-id} \
-DnoCode
cd {create-app-artifact-id}
要创建一个 Gradle 项目,添加 -DbuildTool=gradle
或 -DbuildTool=gradle-kotlin-dsl
选项。
适用于 Windows 用户:
-
如果使用 cmd,(不要使用反斜杠
\
,并将所有内容放在同一行上) -
如果使用 Powershell,将
-D
参数用双引号引起来,例如"-DprojectArtifactId={create-app-artifact-id}"
如果你已经创建了一个项目,可以使用 add-extension
命令将 reactive-pg-client
扩展添加到现有的 Quarkus 项目:
quarkus extension add {add-extension-extensions}
./mvnw quarkus:add-extension -Dextensions='{add-extension-extensions}'
./gradlew addExtension --extensions='{add-extension-extensions}'
否则,你可以手动将依赖项添加到你的构建文件:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-reactive-pg-client</artifactId>
</dependency>
implementation("io.quarkus:quarkus-reactive-pg-client")
Mutiny
Quarkus REST(以前称为 RESTEasy Reactive)开箱即用地支持 Mutiny 类型(例如 Uni
和 Multi
)。
在本指南中,我们将使用 Reactive PostgreSQL 客户端的 Mutiny API。如果你不熟悉 Mutiny,请查看 Mutiny - an intuitive reactive programming library。 |
JSON Binding
我们将在 JSON 格式下通过 HTTP 公开 Fruit
实例。因此,你必须还添加 quarkus-rest-jackson
扩展:
quarkus extension add {add-extension-extensions}
./mvnw quarkus:add-extension -Dextensions='{add-extension-extensions}'
./gradlew addExtension --extensions='{add-extension-extensions}'
如果你不想使用命令行,请手动将依赖项添加到你的构建文件:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-rest-jackson</artifactId>
</dependency>
implementation("io.quarkus:quarkus-rest-jackson")
当然,这仅仅是本指南的要求,而不是使用 Reactive PostgreSQL 客户端的任何应用程序的要求。
Configuring
Reactive PostgreSQL 客户端可以通过标准的 Quarkus 数据源属性和反应式 URL 进行配置:
quarkus.datasource.db-kind=postgresql
quarkus.datasource.username=quarkus_test
quarkus.datasource.password=quarkus_test
quarkus.datasource.reactive.url=postgresql://localhost:5432/quarkus_test
使用该方法,你可以创建 FruitResource
框架并注入一个 io.vertx.mutiny.pgclient.PgPool
实例:
package org.acme.reactive.crud;
import java.net.URI;
import jakarta.ws.rs.DELETE;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.PUT;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.Response.ResponseBuilder;
import jakarta.ws.rs.core.Response.Status;
import io.smallrye.mutiny.Multi;
import io.smallrye.mutiny.Uni;
import io.vertx.mutiny.pgclient.PgPool;
@Path("fruits")
public class FruitResource {
private final PgPool client;
public FruitResource(PgPool client) {
this.client = client;
}
}
Database schema and seed data
在实现 REST 端点和数据管理代码之前,我们必须设置数据库模式。在前期插入一些数据也比较方便。
对于生产,我们建议使用类似于 Flyway database migration tool 的内容。但是对于开发,我们可以在启动时简单地删除并创建表,然后插入一些水果。
package org.acme.reactive.crud;
import io.quarkus.runtime.StartupEvent;
import io.vertx.mutiny.pgclient.PgPool;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.event.Observes;
@ApplicationScoped
public class DBInit {
private final PgPool client;
private final boolean schemaCreate;
public DBInit(PgPool client, @ConfigProperty(name = "myapp.schema.create", defaultValue = "true") boolean schemaCreate) {
this.client = client;
this.schemaCreate = schemaCreate;
}
void onStart(@Observes StartupEvent ev) {
if (schemaCreate) {
initdb();
}
}
private void initdb() {
// TODO
}
}
您可以在 |
快准备好了!在开发模式下初始化数据库,我们将使用客户端简单的 query
方法。它返回一个 Uni
,因此可以组合来顺序执行查询:
client.query("DROP TABLE IF EXISTS fruits").execute()
.flatMap(r -> client.query("CREATE TABLE fruits (id SERIAL PRIMARY KEY, name TEXT NOT NULL)").execute())
.flatMap(r -> client.query("INSERT INTO fruits (name) VALUES ('Kiwi')").execute())
.flatMap(r -> client.query("INSERT INTO fruits (name) VALUES ('Durian')").execute())
.flatMap(r -> client.query("INSERT INTO fruits (name) VALUES ('Pomelo')").execute())
.flatMap(r -> client.query("INSERT INTO fruits (name) VALUES ('Lychee')").execute())
.await().indefinitely();
想知道为什么我们必须在最新查询完成之前进行阻塞吗?此代码是方法的一部分,它 |
就是这样!到目前为止,我们已经了解了如何配置池化客户端和执行简单查询。我们现在可以开发数据管理代码并实现我们的 RESTful 端点。
Using
Query results traversal
在开发模式下,数据库在 fruits
表中设置了几行。若要检索所有数据,我们将再次使用 query
方法:
public static Multi<Fruit> findAll(PgPool client) {
return client.query("SELECT id, name FROM fruits ORDER BY name ASC").execute()
.onItem().transformToMulti(set -> Multi.createFrom().iterable(set)) (1)
.onItem().transform(Fruit::from); (2)
}
private static Fruit from(Row row) {
return new Fruit(row.getLong("id"), row.getString("name"));
}
1 | 将 io.vertx.mutiny.sqlclient.RowSet 变成 Multi<Row> 。 |
2 | 将每个 io.vertx.mutiny.sqlclient.Row 转换为 Fruit 。 |
Fruit#from
方法将 Row
实例转换为 Fruit
实例。将其提取出来是为了方便实现其他数据管理方法。
然后,添加获取后端所有水果的端点:
@GET
public Multi<Fruit> get() {
return Fruit.findAll(client);
}
现在,使用以下方法在开发模式下启动 Quarkus:
quarkus dev
./mvnw quarkus:dev
./gradlew --console=plain quarkusDev
最后,打开浏览器并导航到 [role="bare"][role="bare"]http://localhost:8080/fruits,您应该看到:
[{"id":2,"name":"Durian"},{"id":1,"name":"Kiwi"},{"id":4,"name":"Lychee"},{"id":3,"name":"Pomelo"}]
Prepared queries
Reactive PostgreSQL 客户端还可以准备查询并获取在执行时替换 SQL 语句中的参数:
client.preparedQuery("SELECT id, name FROM fruits WHERE id = $1").execute(Tuple.of(id))
对于 PostgreSQL,SQL 字符串可以通过使用 |
与简单的 query
方法类似, preparedQuery
返回 PreparedQuery<RowSet<Row>>
的实例。借助此工具,我们能够安全地使用用户提供的 id
来获取特定水果的详细信息:
public static Uni<Fruit> findById(PgPool client, Long id) {
return client.preparedQuery("SELECT id, name FROM fruits WHERE id = $1").execute(Tuple.of(id)) (1)
.onItem().transform(RowSet::iterator) (2)
.onItem().transform(iterator -> iterator.hasNext() ? from(iterator.next()) : null); (3)
}
1 | 创建一个 Tuple 来保存已准备的查询参数。 |
2 | 获取 RowSet 结果的 Iterator 。 |
3 | 如果找到实体,从 Row 创建 Fruit 实例。 |
在 Jakarta REST 资源中:
@GET
@Path("{id}")
public Uni<Response> getSingle(Long id) {
return Fruit.findById(client, id)
.onItem().transform(fruit -> fruit != null ? Response.ok(fruit) : Response.status(Status.NOT_FOUND)) (1)
.onItem().transform(ResponseBuilder::build); (2)
}
1 | 准备一个 Jakarta REST 响应,其中包含找到的 Fruit 实例或 404 状态代码。 |
2 | 构建并发送响应。 |
同样的逻辑适用于保存 Fruit
时:
public Uni<Long> save(PgPool client) {
return client.preparedQuery("INSERT INTO fruits (name) VALUES ($1) RETURNING id").execute(Tuple.of(name))
.onItem().transform(pgRowSet -> pgRowSet.iterator().next().getLong("id"));
}
在 Web 资源中,我们处理 POST
请求:
@POST
public Uni<Response> create(Fruit fruit) {
return fruit.save(client)
.onItem().transform(id -> URI.create("/fruits/" + id))
.onItem().transform(uri -> Response.created(uri).build());
}
Result metadata
RowSet
不仅持有内存中的数据,还提供一些关于数据本身的信息,例如:
-
查询影响的行数(根据查询类型插入/删除/更新/检索),
-
the column names.
让我们用它来支持从数据库中删除水果:
public static Uni<Boolean> delete(PgPool client, Long id) {
return client.preparedQuery("DELETE FROM fruits WHERE id = $1").execute(Tuple.of(id))
.onItem().transform(pgRowSet -> pgRowSet.rowCount() == 1); (1)
}
1 | 检查元数据以确定水果是否已实际删除。 |
并在 Web 资源中处理 HTTP DELETE
方法:
@DELETE
@Path("{id}")
public Uni<Response> delete(Long id) {
return Fruit.delete(client, id)
.onItem().transform(deleted -> deleted ? Status.NO_CONTENT : Status.NOT_FOUND)
.onItem().transform(status -> Response.status(status).build());
}
通过实现 GET
、POST
和 DELETE
方法,我们现在可以创建一个最小的网页来试用 RESTful 应用程序。我们使用 jQuery 来简化与后端的交互:
<!doctype html>
<html>
<head>
<meta charset="utf-8"/>
<title>Reactive REST - Quarkus</title>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
<script type="application/javascript" src="fruits.js"></script>
</head>
<body>
<h1>Fruits API Testing</h1>
<h2>All fruits</h2>
<div id="all-fruits"></div>
<h2>Create Fruit</h2>
<input id="fruit-name" type="text">
<button id="create-fruit-button" type="button">Create</button>
<div id="create-fruit"></div>
</body>
</html>
Quarkus 自动供应位于 |
在 JavaScript 代码中,我们需要一个函数来刷新水果列表,当:
-
页面加载时,或
-
添加了一个水果,或
-
a fruit is deleted.
function refresh() {
$.get('/fruits', function (fruits) {
var list = '';
(fruits || []).forEach(function (fruit) { (1)
list = list
+ '<tr>'
+ '<td>' + fruit.id + '</td>'
+ '<td>' + fruit.name + '</td>'
+ '<td><a href="#" onclick="deleteFruit(' + fruit.id + ')">Delete</a></td>'
+ '</tr>'
});
if (list.length > 0) {
list = ''
+ '<table><thead><th>Id</th><th>Name</th><th></th></thead>'
+ list
+ '</table>';
} else {
list = "No fruits in database"
}
$('#all-fruits').html(list);
});
}
function deleteFruit(id) {
$.ajax('/fruits/' + id, {method: 'DELETE'}).then(refresh);
}
$(document).ready(function () {
$('#create-fruit-button').click(function () {
var fruitName = $('#fruit-name').val();
$.post({
url: '/fruits',
contentType: 'application/json',
data: JSON.stringify({name: fruitName})
}).then(refresh);
});
refresh();
});
1 | 数据库为空时未定义 fruits 参数。 |
完成!导航至 [role="bare"][role="bare"]http://localhost:8080/fruits.html 并读取/创建/删除一些水果。
Database Clients details
Database | Extension name | Pool class name | Placeholders |
---|---|---|---|
IBM Db2 |
|
|
|
MariaDB/MySQL |
|
|
|
Microsoft SQL Server |
|
|
|
Oracle |
|
|
|
PostgreSQL |
|
|
|
Transactions
反应式 SQL 客户端支持事务。事务通过 io.vertx.mutiny.sqlclient.SqlConnection#begin
启动并通过 io.vertx.mutiny.sqlclient.Transaction#commit
或 io.vertx.mutiny.sqlclient.Transaction#rollback
终止。所有这些操作都是异步的:
-
connection.begin()
returns aUni<Transaction>
-
transaction.commit()
和transaction.rollback()
返回Uni<Void>
在响应式编程世界中管理事务可能很繁琐。您可以使用 io.vertx.mutiny.sqlclient.Pool#withTransaction
帮助程序方法,而不是编写重复且复杂的(因而容易出错!)代码。
以下代码段展示了如何在同一事务中运行 2 个插入:
public static Uni<Void> insertTwoFruits(PgPool client, Fruit fruit1, Fruit fruit2) {
return client.withTransaction(conn -> {
Uni<RowSet<Row>> insertOne = conn.preparedQuery("INSERT INTO fruits (name) VALUES ($1) RETURNING id")
.execute(Tuple.of(fruit1.name));
Uni<RowSet<Row>> insertTwo = conn.preparedQuery("INSERT INTO fruits (name) VALUES ($1) RETURNING id")
.execute(Tuple.of(fruit2.name));
return Uni.combine().all().unis(insertOne, insertTwo)
// Ignore the results (the two ids)
.discardItems();
});
}
在此示例中,事务在成功时自动提交或在失败时回滚。
你还可以按照如下方式创建相关动作:
return client.withTransaction(conn -> conn
.preparedQuery("INSERT INTO person (firstname,lastname) VALUES ($1,$2) RETURNING id")
.execute(Tuple.of(person.getFirstName(), person.getLastName()))
.onItem().transformToUni(id -> conn.preparedQuery("INSERT INTO addr (person_id,addrline1) VALUES ($1,$2)")
.execute(Tuple.of(id.iterator().next().getLong("id"), person.getLastName())))
.onItem().ignore().andContinueWithNull());
Working with batch query results
在执行批处理查询时,响应式 SQL 客户端会返回一个 RowSet
,该批次的结果与第一个元素相对应。要获取以下批处理元素的结果,您必须调用 RowSet#next
方法,直到它返回 null
。
假设您想要更新一些行并计算受影响的行总数。您必须检查每个 RowSet
:
PreparedQuery<RowSet<Row>> preparedQuery = client.preparedQuery("UPDATE fruits SET name = $1 WHERE id = $2");
Uni<RowSet<Row>> rowSet = preparedQuery.executeBatch(Arrays.asList(
Tuple.of("Orange", 1),
Tuple.of("Pear", 2),
Tuple.of("Apple", 3)));
Uni<Integer> totalAffected = rowSet.onItem().transform(res -> {
int total = 0;
do {
total += res.rowCount(); (1)
} while ((res = res.next()) != null); (2)
return total;
});
1 | 计算 RowSet#rowCount 的和。 |
2 | 调用 RowSet#next ,直到它返回 null 。 |
作为另一个示例,如果您想要加载您刚刚插入的所有行,您必须连接每个 RowSet
的内容:
PreparedQuery<RowSet<Row>> preparedQuery = client.preparedQuery("INSERT INTO fruits (name) VALUES ($1) RETURNING *");
Uni<RowSet<Row>> rowSet = preparedQuery.executeBatch(Arrays.asList(
Tuple.of("Orange"),
Tuple.of("Pear"),
Tuple.of("Apple")));
// Generate a Multi of RowSet items
Multi<RowSet<Row>> rowSets = rowSet.onItem().transformToMulti(res -> {
return Multi.createFrom().generator(() -> res, (rs, emitter) -> {
RowSet<Row> next = null;
if (rs != null) {
emitter.emit(rs);
next = rs.next();
}
if (next == null) {
emitter.complete();
}
return next;
});
});
// Transform each RowSet into Multi of Row items and Concatenate
Multi<Row> rows = rowSets.onItem().transformToMultiAndConcatenate(Multi.createFrom()::iterable);
Multiple Datasources
反应式 SQL 客户端支持定义多个数据源。
使用多个数据源的典型配置如下所示:
quarkus.datasource.db-kind=postgresql 1
quarkus.datasource.username=user-default
quarkus.datasource.password=password-default
quarkus.datasource.reactive.url=postgresql://localhost:5432/default
quarkus.datasource."additional1".db-kind=postgresql 2
quarkus.datasource."additional1".username=user-additional1
quarkus.datasource."additional1".password=password-additional1
quarkus.datasource."additional1".reactive.url=postgresql://localhost:5432/additional1
quarkus.datasource."additional2".db-kind=mysql 3
quarkus.datasource."additional2".username=user-additional2
quarkus.datasource."additional2".password=password-additional2
quarkus.datasource."additional2".reactive.url=mysql://localhost:3306/additional2
1 | 默认数据源 - 使用 PostgreSQL。 |
2 | 使用 PostgreSQL 的名为 additional1 的命名数据源。 |
3 | 使用 MySQL 的名为 additional2 的命名数据源。 |
然后你可以如下一般注入客户端:
@Inject 1
PgPool defaultClient;
@Inject
@ReactiveDataSource("additional1") 2
PgPool additional1Client;
@Inject
@ReactiveDataSource("additional2")
MySQLPool additional2Client;
1 | 注入默认数据源的客户端不需要任何特殊操作。 |
2 | 对于命名数据源,请将 @ReactiveDataSource CDI 限定符连同数据源名称作为其值使用。 |
UNIX Domain Socket connections
可以将 PostgreSQL 和 MariaDB/MySQL 客户端配置为通过 UNIX 域套接字连接服务器。
首先确保 native transport support 已启用。
然后配置数据库连接 URL。此步骤取决于数据库类型。
Load-balancing connections
响应式 PostgreSQL 和 MariaDB/MySQL 客户端支持定义多种连接。
具有多种连接的典型配置如下:
quarkus.datasource.reactive.url=postgresql://host1:5432/default,postgresql://host2:5432/default,postgresql://host3:5432/default
这也可以用索引属性语法编写:
quarkus.datasource.reactive.url[0]=postgresql://host1:5432/default
quarkus.datasource.reactive.url[1]=postgresql://host2:5432/default
quarkus.datasource.reactive.url[2]=postgresql://host3:5432/default
Pooled connection idle-timeout
响应式数据源可以使用 `idle-timeout`进行配置。它是连接在池中保持未使用的最长时间,然后再关闭。
`idle-timeout`在默认情况下被禁用。 |
例如,你可以在 60 分钟后使空闲连接失效:
quarkus.datasource.reactive.idle-timeout=PT60M
Pooled Connection max-lifetime
除了 `idle-timeout`之外,响应式数据源还可以使用 `max-lifetime`进行配置。它是连接在池中保持的最长时间,然后根据需要关闭并替换。`max-lifetime`确保池有最新配置的最新连接。
`max-lifetime`在默认情况下被禁用,但在使用能提供限时凭据的凭据提供程序(如 Vault credentials provider)时,它是重要的配置。 |
例如,你可以确保连接在 60 分钟后被回收:
quarkus.datasource.reactive.max-lifetime=PT60M
Customizing pool creation
有时,只通过声明无法配置数据库连接池。
例如,您可能必须读取生产中才有的特定文件,或者从专有配置服务器中检索配置数据。
在这种情况下,您可以通过创建实现取决于目标数据库的接口的类来自定义池创建:
Database | Pool creator class name |
---|---|
IBM Db2 |
|
MariaDB/MySQL |
|
Microsoft SQL Server |
|
Oracle |
|
PostgreSQL |
|
voici un exemple pour PostgreSQL :
import jakarta.inject.Singleton;
import io.quarkus.reactive.pg.client.PgPoolCreator;
import io.vertx.pgclient.PgConnectOptions;
import io.vertx.pgclient.PgPool;
import io.vertx.sqlclient.PoolOptions;
@Singleton
public class CustomPgPoolCreator implements PgPoolCreator {
@Override
public PgPool create(Input input) {
PgConnectOptions connectOptions = input.pgConnectOptions();
PoolOptions poolOptions = input.poolOptions();
// Customize connectOptions, poolOptions or both, as required
return PgPool.pool(input.vertx(), connectOptions, poolOptions);
}
}
Pipelining
Les clients PostgreSQL et MariaDB/MySQL prennent en charge le traitement pipeliné des requêtes au niveau de la connexion. Cette fonctionnalité consiste à envoyer plusieurs requêtes sur la même connexion à la base de données sans attendre les réponses correspondantes.
Dans certains cas d’utilisation, le traitement en pipeline des requêtes peut améliorer les performances d’accès à la base de données.
voici un exemple pour PostgreSQL :
import jakarta.inject.Inject;
import io.smallrye.mutiny.Uni;
import io.vertx.mutiny.pgclient.PgPool;
public class PipeliningExample {
@Inject
PgPool client;
public Uni<String> favoriteFruitAndVegetable() {
// Explicitly acquire a connection
return client.withConnection(conn -> {
Uni<String> favoriteFruit = conn.query("SELECT name FROM fruits WHERE preferred IS TRUE").execute()
.onItem().transform(rows -> rows.iterator().next().getString("name"));
Uni<String> favoriteVegetable = conn.query("SELECT name FROM vegetables WHERE preferred IS TRUE").execute()
.onItem().transform(rows -> rows.iterator().next().getString("name"));
// favoriteFruit and favoriteVegetable unis will be subscribed at the same time
return Uni.combine().all().unis(favoriteFruit, favoriteVegetable)
.combinedWith(PipeliningExample::formatMessage);
});
}
private static String formatMessage(String fruit, String vegetable) {
return String.format("The favorite fruit is %s and the favorite vegetable is %s", fruit, vegetable);
}
}
Le nombre maximal de requêtes en pipeline est configuré avec la propriété pipelining-limit
:
# For PostgreSQL
quarkus.datasource.reactive.postgresql.pipelining-limit=256
# For MariaDB/MySQL
quarkus.datasource.reactive.mysql.pipelining-limit=256
Par défaut, pipelining-limit
est défini sur 256.
Configuration Reference
Common Datasource
Unresolved include directive in modules/ROOT/pages/reactive-sql-clients.adoc - include::../../../target/quarkus-generated-doc/config/quarkus-datasource.adoc[]
Reactive Datasource
Unresolved include directive in modules/ROOT/pages/reactive-sql-clients.adoc - include::../../../target/quarkus-generated-doc/config/quarkus-reactive-datasource.adoc[]
IBM Db2
Unresolved include directive in modules/ROOT/pages/reactive-sql-clients.adoc - include::../../../target/quarkus-generated-doc/config/quarkus-reactive-db2-client.adoc[]
MariaDB/MySQL
Unresolved include directive in modules/ROOT/pages/reactive-sql-clients.adoc - include::../../../target/quarkus-generated-doc/config/quarkus-reactive-mysql-client.adoc[]
Microsoft SQL Server
Unresolved include directive in modules/ROOT/pages/reactive-sql-clients.adoc - include::../../../target/quarkus-generated-doc/config/quarkus-reactive-mssql-client.adoc[]