リアクティブ SQL クライアント
Reactive SQL クライアントは、スケーラビリティと低オーバーヘッドに焦点を当てたシンプルな API を持っています。現在、以下のデータベースサーバーがサポートされています。
-
IBM Db2
-
PostgreSQL
-
MariaDB/MySQL
-
Microsoft SQL Server
-
Oracle
Reactive SQL Client for Oracle は、techpreview と見なされます。 tech preview モードでは、アイデアを成熟させるために早期のフィードバックが求められます。ソリューションが成熟するまでの間、プラットフォームの安定性を保証するものではありません。フィードバックは mailing list や GitHub issue tracker で受け付けています。 |
このガイドでは、PostgreSQL に格納されたデータをRESTful APIで公開するシンプルなCRUDアプリケーションの実装方法を学びます。
各クライアントのエクステンションと接続プールのクラス名は、このドキュメントの下部に記載されています。 |
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;
}
}
要件
このガイドを完成させるには、以下が必要です:
-
約15分
-
IDE
-
JDK 17+がインストールされ、
JAVA_HOME
が適切に設定されていること -
Apache Maven 3.9.9
-
動作するコンテナランタイム(Docker, Podman)
-
使用したい場合は、 Quarkus CLI
-
ネイティブ実行可能ファイルをビルドしたい場合、MandrelまたはGraalVM(あるいはネイティブなコンテナビルドを使用する場合はDocker)をインストールし、 適切に設定していること
アプリケーションを開発モードで起動すると、Quarkus はすぐに使用できる zero-config database を提供します。 事前にデータベースを起動することもできます。
|
ソリューション
次の章で紹介する手順に沿って、ステップを踏んでアプリケーションを作成することを推奨します。 ただし、完成した例にそのまま進むこともできます。
git clone https://github.com/quarkusio/quarkus-quickstarts.git
で Git リポジトリーをクローンします。または、https://github.com/quarkusio/quarkus-quickstarts/archive/main.zip[アーカイブ] をダウンロードします。
解決策は、 getting-started-reactive-crud
ディレクトリー を参照してください。
インストール
リアクティブな PostgreSQL クライアントエクステンション
まず、プロジェクトで quarkus-reactive-pg-client
のエクステンションが有効になっていることを確認します。新しいプロジェクトを作成する場合は、次のコマンドを使用します。
Windowsユーザーの場合:
-
cmdを使用する場合、(バックスラッシュ
\
を使用せず、すべてを同じ行に書かないでください)。 -
Powershellを使用する場合は、
-D
パラメータを二重引用符で囲んでください。例:"-DprojectArtifactId=reactive-pg-client-quickstart"
すでに作成済みのプロジェクトがある場合は、 add-extension
コマンドで既存のQuarkusプロジェクトに reactive-pg-client
エクステンションを追加することが出来ます。
quarkus extension add reactive-pg-client
./mvnw quarkus:add-extension -Dextensions='reactive-pg-client'
./gradlew addExtension --extensions='reactive-pg-client'
それ以外の場合は、ビルドファイルに依存関係を手動で追加できます。
<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 Client の Mutiny API を使用します。Mutiny についてよく知らない方は、Mutiny - an intuitive reactive programming library を参照してください。 |
JSON バインディング
Fruit
インスタンスを HTTP 経由で JSON 形式で公開します。
したがって、 quarkus-rest-jackson
エクステンションも追加する必要があります。
quarkus extension add rest-jackson
./mvnw quarkus:add-extension -Dextensions='rest-jackson'
./gradlew addExtension --extensions='rest-jackson'
コマンドラインを使用したくない場合は、ビルドファイルに依存関係を手動で追加します。
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-rest-jackson</artifactId>
</dependency>
implementation("io.quarkus:quarkus-rest-jackson")
もちろん、これはこのガイドの要件に過ぎず、Reactive PostgreSQLクライアントを使用したアプリケーションではありません。
設定
Reactive PostgreSQLクライアントは、Quarkusの標準的なデータソースプロパティーとReactive 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;
}
}
データベーススキーマとシードデータ
REST エンドポイントとデータ管理コードを実装する前に、データベーススキーマを設定する必要があります。 事前に何らかのデータを挿入しておくと便利です。
本番環境では Flyway データベースマイグレーションツール のようなものを使用することをお勧めします。しかし、開発時には単純に起動時にテーブルをドロップして作成し、いくつかの fruits を挿入することができます。
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
}
}
application.properties ファイルの myapp.schema.create プロパティーのデフォルト値を上書きできます。
|
ほとんど準備ができています! 開発モードで DB を初期化するには、クライアントの単純な 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 エンドポイントを実装する準備が整いました。
使用
クエリー結果のトラバーサル
開発モードでは、データベースは 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
インスタンスに変換します。これは、他のデータ管理方法の実装の便宜上、展開されています。
次に、バックエンドからすべての fruits を取得するためのエンドポイントを追加します。
@GET
public Multi<Fruit> get() {
return Fruit.findAll(client);
}
ここで、開発モードで Quarkus を起動します。
quarkus dev
./mvnw quarkus:dev
./gradlew --console=plain quarkusDev
最後に、ブラウザーを開いて http://localhost:8080/fruits に移動します。次のように表示されます。
[{"id":2,"name":"Durian"},{"id":1,"name":"Kiwi"},{"id":4,"name":"Lychee"},{"id":3,"name":"Pomelo"}]
プリペアドクエリー
Reactive PostgreSQL Client は、クエリーを準備し、実行時に SQL ステートメントにおいて置き換えられるパラメーターを持つこともできます。
client.preparedQuery("SELECT id, name FROM fruits WHERE id = $1").execute(Tuple.of(id))
PostgreSQL の場合、SQL 文字列は $1 、 $2 …などを使用して位置でパラメーターを参照できます。
他のデータベースについては データベースクライアントの詳細 セクションを参照してください。
|
単純な query
メソッドと同様に、 preparedQuery
は PreparedQuery<RowSet<Row>>
のインスタンスを返します。このツールを装備すると、ユーザーから提供された id
を安全に使用して、特定の fruit の詳細を取得できます。
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 | 見つかった場合、 Fruit インスタンス、あるいは 404 ステータスコードでJakarta REST 応答を準備します。 |
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());
}
結果のメタデータ
RowSet
はデータをメモリーに保持するだけでなく、次のようなデータ自体に関する情報も提供します。
-
クエリーの影響を受ける行数 (クエリータイプに応じて挿入/削除/更新/取得)、
-
列名。
これを使用して、データベース内の fruits の削除をサポートしましょう。
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 | メタデータを調べて、fruit が実際に削除されたかどうかを判断します。 |
また、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 アプリケーションを試すための最小限の Web ページを作成できます。 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 は、 META-INF/resources ディレクトリーの下にある静的リソースを自動的に提供します。
|
JavaScript コードでは、次の場合に fruits のリストを更新する関数が必要です。
-
ページが読み込まれる、または
-
fruit が追加される、または
-
fruit は削除される。
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 パラメーターは定義されません。 |
すべて完了! http://localhost:8080/fruits.html に移動し、いくつかの fruits を読み取り/作成/削除します。
データベースクライアントの詳細
データベース | 拡張子名 | プールクラス名 | プレースホルダー |
---|---|---|---|
IBM Db2 |
|
|
|
MariaDB/MySQL |
|
|
|
Microsoft SQL Server |
|
|
|
Oracle |
|
|
|
PostgreSQL |
|
|
|
トランザクション
リアクティブ SQL クライアントはトランザクションをサポートします。トランザクションは io.vertx.mutiny.sqlclient.SqlConnection#begin
で開始され、 io.vertx.mutiny.sqlclient.Transaction#commit
または io.vertx.mutiny.sqlclient.Transaction#rollback
で終了します。これらの操作はすべて非同期です。
-
connection.begin()`は `Uni<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());
バッチクエリー結果の操作
バッチクエリーを実行すると、リアクティブ SQL クライアントはバッチの最初の要素の結果に対応する RowSet
を返します。次のバッチ要素の結果を取得するには、 null
が返されるまで RowSet#next
メソッドを呼び出す必要があります。
いくつかの行を更新し、影響を受ける行の総数を計算するとします。各 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 | null を返すまで RowSet#next を呼び出します。 |
別の例として、挿入したばかりのすべての行をロードする場合は、各 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);
複数のデータソース
Reactive 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 | additional1 と呼ばれる名前付きデータソース - PostgreSQL を使用。 |
3 | additional2 と呼ばれる名前付きデータソース - MySQL を使用。 |
次に、次のようにクライアントを挿入できます。
@Inject (1)
PgPool defaultClient;
@Inject
@ReactiveDataSource("additional1") (2)
PgPool additional1Client;
@Inject
@ReactiveDataSource("additional2")
MySQLPool additional2Client;
1 | デフォルトのデータソースにクライアントを挿入するために特別なことは何も必要ありません。 |
2 | 名前付きデータソースの場合、値としてデータソース名を指定して @ReactiveDataSource CDI 修飾子を使用します。 |
UNIX ドメインソケット接続
PostgreSQL および MariaDB/MySQL クライアントは、UNIX ドメインソケットを介してサーバーに接続するように設定できます。
まず、native transport support が有効になっていることを確認します。
次に、データベース接続の URL を設定します。この手順は、データベースのタイプによって異なります。
PostgreSQL
PostgreSQL ドメインソケットパスの形式は、 <directory>/.s.PGSQL.<port>
のようになります。
データベース接続の URL は、次のように設定する必要があります。
-
host
はソケットパスのdirectory
です -
port
はソケットパスのport
です
次のソケットパスを検討してください: /var/run/postgresql/.s.PGSQL.5432
。
application.properties
で以下を追加します。
quarkus.datasource.reactive.url=postgresql://:5432/quarkus_test?host=/var/run/postgresql
ロードバランシングコネクション
リアクティブ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
プールされた接続 idle-timeout
リアクティブデータソースは、 idle-timeout
で設定できます。これは、接続が閉じられる前に、接続がプール内で未使用のままである最大時間です。
idle-timeout はデフォルトで無効になっています。
|
たとえば、アイドル状態の接続を 60 分後に期限切れにすることができます。
quarkus.datasource.reactive.idle-timeout=PT60M
プールされた接続 max-lifetime
idle-timeout
に加えて、リアクティブデータソースは max-lifetime
を使用して設定することもできます。
これは、接続が切断され、必要に応じて置き換えられるまでに、接続がプール内に留まる最大時間です。
max-lifetime
を使用すると、プールに最新の設定の新しい接続が確保されます。
`max-lifetime`はデフォルトでは無効になっていますが、 Vault 認証情報プロバイダー のような時間制限のある認証情報を提供する認証情報プロバイダーを使用する場合に重要な設定です。 |
たとえば、60 分後に接続が再利用されるように指定できます。
quarkus.datasource.reactive.max-lifetime=PT60M
プール作成のカスタマイズ
データベース接続プールは、宣言だけでは設定できないことがあります。
たとえば、実稼働環境にのみ存在する特定のファイルを読み取ったり、独自の設定サーバーから設定データを取得したりする必要がある場合があります。
この場合、対象データベースに依存するインターフェイスを実装したクラスを作成することで、プール作成をカスタマイズすることができます:
データベース | プール作成者クラス名 |
---|---|
IBM Db2 |
|
MariaDB/MySQL |
|
Microsoft SQL Server |
|
Oracle |
|
PostgreSQL |
|
ここでは、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);
}
}
パイプライン
PostgreSQL および MariaDB/MySQL クライアントは、接続レベルでのクエリーのパイプライン化をサポートしています。 この機能には、対応する応答を待たずに、同じデータベース接続で複数のクエリーを送信する機能などが含まれます。
ユースケースによっては、クエリーパイプラインによってデータベースアクセスのパフォーマンスが向上する場合があります。
ここでは、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);
}
}
パイプラインクエリーの最大数は、 pipelining-limit
プロパティーで設定されます。
# For PostgreSQL
quarkus.datasource.reactive.postgresql.pipelining-limit=256
# For MariaDB/MySQL
quarkus.datasource.reactive.mysql.pipelining-limit=256
デフォルトでは、 pipelining-limit
は 256 に設定されています。
設定リファレンス
共通のデータソース
ビルド時に固定された設定プロパティー。その他の設定プロパティーは、すべて実行時にオーバーライド可能です。
Configuration property |
型 |
デフォルト |
||
---|---|---|---|---|
Whether or not a health check is published in case the smallrye-health extension is present. This is a global setting and is not specific to a datasource. Environment variable: Show more |
boolean |
|
||
Whether or not datasource metrics are published in case a metrics extension is present. This is a global setting and is not specific to a datasource.
Environment variable: Show more |
boolean |
|
||
The kind of database we will connect to (e.g. h2, postgresql…). Environment variable: Show more |
string |
|||
The version of the database we will connect to (e.g. '10.0').
As a rule, the version set here should be as high as possible, but must be lower than or equal to the version of any database your application will connect to. A high version will allow better performance and using more features (e.g. Hibernate ORM may generate more efficient SQL, avoid workarounds and take advantage of more database features), but if it is higher than the version of the database you want to connect to, it may lead to runtime exceptions (e.g. Hibernate ORM may generate invalid SQL that your database will reject). Some extensions (like the Hibernate ORM extension) will try to check this version against the actual database version on startup, leading to a startup failure when the actual version is lower or simply a warning in case the database cannot be reached. The default for this property is specific to each extension; the Hibernate ORM extension will default to the oldest version it supports. Environment variable: Show more |
string |
|||
Whether this particular data source should be excluded from the health check if the general health check for data sources is enabled. By default, the health check includes all configured data sources (if it is enabled). Environment variable: Show more |
boolean |
|
||
Whether this datasource should be active at runtime. Environment variable: Show more |
boolean |
|
||
The datasource username Environment variable: Show more |
string |
|||
The datasource password Environment variable: Show more |
string |
|||
The credentials provider name Environment variable: Show more |
string |
|||
The credentials provider bean name. This is a bean name (as in For Vault, the credentials provider bean name is Environment variable: Show more |
string |
|||
型 |
デフォルト |
|||
Whether this Dev Service should start with the application in dev mode or tests. Dev Services are enabled by default unless connection configuration (e.g. the JDBC URL or reactive client URL) is set explicitly. Environment variable: Show more |
boolean |
|||
The container image name for container-based Dev Service providers. This has no effect if the provider is not a container-based database, such as H2 or Derby. Environment variable: Show more |
string |
|||
Environment variables that are passed to the container. Environment variable: Show more |
Map<String,String> |
|||
Generic properties that are passed for additional container configuration. Properties defined here are database-specific and are interpreted specifically in each database dev service implementation. Environment variable: Show more |
Map<String,String> |
|||
Generic properties that are added to the database connection URL. Environment variable: Show more |
Map<String,String> |
|||
Optional fixed port the dev service will listen to. If not defined, the port will be chosen randomly. Environment variable: Show more |
int |
|||
The container start command to use for container-based Dev Service providers. This has no effect if the provider is not a container-based database, such as H2 or Derby. Environment variable: Show more |
string |
|||
The database name to use if this Dev Service supports overriding it. Environment variable: Show more |
string |
|||
The username to use if this Dev Service supports overriding it. Environment variable: Show more |
string |
|||
The password to use if this Dev Service supports overriding it. Environment variable: Show more |
string |
|||
The paths to SQL scripts to be loaded from the classpath and applied to the Dev Service database. This has no effect if the provider is not a container-based database, such as H2 or Derby. Environment variable: Show more |
list of string |
|||
The volumes to be mapped to the container. The map key corresponds to the host location; the map value is the container location. If the host location starts with "classpath:", the mapping loads the resource from the classpath with read-only permission. When using a file system location, the volume will be generated with read-write permission, potentially leading to data loss or modification in your file system. This has no effect if the provider is not a container-based database, such as H2 or Derby. Environment variable: Show more |
Map<String,String> |
|||
Whether to keep Dev Service containers running after a dev mode session or test suite execution to reuse them in the next dev mode session or test suite execution. Within a dev mode session or test suite execution, Quarkus will always reuse Dev Services as long as their configuration (username, password, environment, port bindings, …) did not change. This feature is specifically about keeping containers running when Quarkus is not running to reuse them across runs.
This configuration property is set to Environment variable: Show more |
boolean |
|
||
Whether the logs should be consumed by the JBoss logger. This has no effect if the provider is not a container-based database, such as H2 or Derby. Environment variable: Show more |
boolean |
|
リアクティブデータソース
ビルド時に固定された設定プロパティー。その他の設定プロパティーは、すべて実行時にオーバーライド可能です。
Configuration property |
型 |
デフォルト |
---|---|---|
If we create a Reactive datasource for this datasource. Environment variable: Show more |
boolean |
|
Whether prepared statements should be cached on the client side. Environment variable: Show more |
boolean |
|
The datasource URLs. If multiple values are set, this datasource will create a pool with a list of servers instead of a single server. The pool uses round-robin load balancing for server selection during connection establishment. Note that certain drivers might not accommodate multiple values in this context. Environment variable: Show more |
list of string |
|
The datasource pool maximum size. Environment variable: Show more |
int |
|
When a new connection object is created, the pool assigns it an event loop. When Environment variable: Show more |
int |
|
Whether all server certificates should be trusted. Environment variable: Show more |
boolean |
|
PEM Trust config is disabled by default. Environment variable: Show more |
boolean |
|
Comma-separated list of the trust certificate files (Pem format). Environment variable: Show more |
list of string |
|
JKS config is disabled by default. Environment variable: Show more |
boolean |
|
Path of the key file (JKS format). Environment variable: Show more |
string |
|
Password of the key file. Environment variable: Show more |
string |
|
PFX config is disabled by default. Environment variable: Show more |
boolean |
|
Path to the key file (PFX format). Environment variable: Show more |
string |
|
Password of the key. Environment variable: Show more |
string |
|
PEM Key/cert config is disabled by default. Environment variable: Show more |
boolean |
|
Comma-separated list of the path to the key files (Pem format). Environment variable: Show more |
list of string |
|
Comma-separated list of the path to the certificate files (Pem format). Environment variable: Show more |
list of string |
|
JKS config is disabled by default. Environment variable: Show more |
boolean |
|
Path of the key file (JKS format). Environment variable: Show more |
string |
|
Password of the key file. Environment variable: Show more |
string |
|
PFX config is disabled by default. Environment variable: Show more |
boolean |
|
Path to the key file (PFX format). Environment variable: Show more |
string |
|
Password of the key. Environment variable: Show more |
string |
|
The number of reconnection attempts when a pooled connection cannot be established on first try. Environment variable: Show more |
int |
|
The interval between reconnection attempts when a pooled connection cannot be established on first try. Environment variable: Show more |
|
|
The hostname verification algorithm to use in case the server’s identity should be checked. Should be Environment variable: Show more |
string |
|
The maximum time a connection remains unused in the pool before it is closed. Environment variable: Show more |
|
|
The maximum time a connection remains in the pool, after which it will be closed upon return and replaced as necessary. Environment variable: Show more |
|
|
Set to true to share the pool among datasources. There can be multiple shared pools distinguished by name, when no specific name is set, the Environment variable: Show more |
boolean |
|
Set the pool name, used when the pool is shared among datasources, otherwise ignored. Environment variable: Show more |
string |
|
Other unspecified properties to be passed through the Reactive SQL Client directly to the database when new connections are initiated. Environment variable: Show more |
Map<String,String> |
期間フォーマットについて
期間の値を書くには、標準の 数字で始まる簡略化した書式を使うこともできます:
その他の場合は、簡略化されたフォーマットが解析のために
|
IBM Db2
ビルド時に固定された設定プロパティー。その他の設定プロパティーは、すべて実行時にオーバーライド可能です。
Configuration property |
型 |
デフォルト |
---|---|---|
型 |
デフォルト |
|
Whether SSL/TLS is enabled. Environment variable: Show more |
boolean |
|
MariaDB/MySQL
ビルド時に固定された設定プロパティー。その他の設定プロパティーは、すべて実行時にオーバーライド可能です。
Configuration property |
型 |
デフォルト |
---|---|---|
型 |
デフォルト |
|
Charset for connections. Environment variable: Show more |
string |
|
Collation for connections. Environment variable: Show more |
string |
|
Desired security state of the connection to the server. Environment variable: Show more |
|
|
Connection timeout in seconds Environment variable: Show more |
int |
|
The authentication plugin the client should use. By default, it uses the plugin name specified by the server in the initial handshake packet. Environment variable: Show more |
|
|
The maximum number of inflight database commands that can be pipelined. By default, pipelining is disabled. Environment variable: Show more |
int |
|
Whether to return the number of rows matched by the WHERE clause in UPDATE statements, instead of the number of rows actually changed. Environment variable: Show more |
ブーリアン |
|
Microsoft SQL Server
ビルド時に固定された設定プロパティー。その他の設定プロパティーは、すべて実行時にオーバーライド可能です。
Configuration property |
型 |
デフォルト |
---|---|---|
型 |
デフォルト |
|
The desired size (in bytes) for TDS packets. Environment variable: Show more |
int |
|
Whether SSL/TLS is enabled. Environment variable: Show more |
boolean |
|
Oracle
ビルド時に固定された設定プロパティー。その他の設定プロパティーは、すべて実行時にオーバーライド可能です。
Configuration property |
型 |
デフォルト |
---|---|---|
No configuration properties found. |
PostgreSQL
ビルド時に固定された設定プロパティー。その他の設定プロパティーは、すべて実行時にオーバーライド可能です。
Configuration property |
型 |
デフォルト |
---|---|---|
型 |
デフォルト |
|
The maximum number of inflight database commands that can be pipelined. Environment variable: Show more |
int |
|
SSL operating mode of the client. Environment variable: Show more |
|
|
Level 7 proxies can load balance queries on several connections to the actual database. When it happens, the client can be confused by the lack of session affinity and unwanted errors can happen like ERROR: unnamed prepared statement does not exist (26000). See Using a level 7 proxy Environment variable: Show more |
boolean |
|