响应式SQL客户端
The Reactive SQL Clients have a straightforward API focusing on scalability and low-overhead. Currently, the following database servers are supported:
-
IBM Db2
-
PostgreSQL
-
MariaDB/MySQL
-
Microsoft SQL Server
-
Oracle
The Reactive SQL Client for Oracle is considered tech preview. In tech preview mode, early feedback is requested to mature the idea. There is no guarantee of stability in the platform until the solution matures. Feedback is welcome on our mailing list or as issues in our GitHub issue tracker. |
In this guide, you will learn how to implement a simple CRUD application exposing data stored in PostgreSQL over a RESTful API.
Extension and connection pool class names for each client can be found at the bottom of this document. |
If you are not familiar with the Quarkus Vert.x extension, consider reading the Using Eclipse Vert.x guide first. |
The application shall manage fruit entities:
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分钟
-
编辑器
-
JDK 17+ installed with
JAVA_HOME
configured appropriately -
Apache Maven 3.9.9
-
A working container runtime (Docker or Podman)
-
如果你愿意的话,还可以选择使用Quarkus CLI
-
如果你想构建原生可执行程序,可以选择安装Mandrel或者GraalVM,并正确配置(或者使用Docker在容器中进行构建)
If you start the application in dev mode, Quarkus provides you with a zero-config database out of the box. You might also start a database up front:
|
解决方案
我们建议您按照下一节的说明逐步创建应用程序。然而,您可以直接转到已完成的示例。
克隆 Git 仓库。 git clone https://github.com/quarkusio/quarkus-quickstarts.git
,或者下载一个 存档 。
The solution is located in the getting-started-reactive-crud
directory.
Installing
Reactive PostgreSQL Client extension
First, make sure your project has the quarkus-reactive-pg-client
extension enabled.
If you are creating a new project, use the following command:
For Windows users:
-
If using cmd, (don’t use backward slash
\
and put everything on the same line) -
If using Powershell, wrap
-D
parameters in double quotes e.g."-DprojectArtifactId=reactive-pg-client-quickstart"
If you have an already created project, the reactive-pg-client
extension can be added to an existing Quarkus project with the add-extension
command:
quarkus extension add reactive-pg-client
./mvnw quarkus:add-extension -Dextensions='reactive-pg-client'
./gradlew addExtension --extensions='reactive-pg-client'
Otherwise, you can manually add the dependency to your build file:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-reactive-pg-client</artifactId>
</dependency>
implementation("io.quarkus:quarkus-reactive-pg-client")
Mutiny
Quarkus REST (formerly RESTEasy Reactive) includes supports for Mutiny types (e.g. Uni
and Multi
) out of the box.
In this guide, we will use the Mutiny API of the Reactive PostgreSQL Client. If you are not familiar with Mutiny, check Mutiny - an intuitive reactive programming library. |
JSON Binding
We will expose Fruit
instances over HTTP in the JSON format.
Consequently, you must also add the quarkus-rest-jackson
extension:
quarkus extension add rest-jackson
./mvnw quarkus:add-extension -Dextensions='rest-jackson'
./gradlew addExtension --extensions='rest-jackson'
If you prefer not to use the command line, manually add the dependency to your build file:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-rest-jackson</artifactId>
</dependency>
implementation("io.quarkus:quarkus-rest-jackson")
Of course, this is only a requirement for this guide, not any application using the Reactive PostgreSQL Client.
Configuring
The Reactive PostgreSQL Client can be configured with standard Quarkus datasource properties and a 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
With that you can create your FruitResource
skeleton and inject a io.vertx.mutiny.pgclient.PgPool
instance:
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
Before we implement the REST endpoint and data management code, we must set up the database schema. It would also be convenient to have some data inserted up front.
For production, we would recommend to use something like the Flyway database migration tool. But for development we can simply drop and create the tables on startup, and then insert a few 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
}
}
You might override the default value of the myapp.schema.create property in the application.properties file.
|
Almost ready!
To initialize the DB in development mode, we will use the client simple query
method.
It returns a Uni
and thus can be composed to execute queries sequentially:
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();
Wondering why we must block until the latest query is completed?
This code is part of a method that |
That’s it! So far we have seen how to configure a pooled client and execute simple queries. We are now ready to develop the data management code and implement our RESTful endpoint.
Using
Query results traversal
In development mode, the database is set up with a few rows in the fruits
table.
To retrieve all the data, we will use the query
method again:
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 | Transform the io.vertx.mutiny.sqlclient.RowSet to a Multi<Row> . |
2 | Convert each io.vertx.mutiny.sqlclient.Row to a Fruit . |
The Fruit#from
method converts a Row
instance to a Fruit
instance.
It is extracted as a convenience for the implementation of the other data management methods.
Then, add the endpoint to get all fruits from the backend:
@GET
public Multi<Fruit> get() {
return Fruit.findAll(client);
}
Now start Quarkus in dev mode with:
quarkus dev
./mvnw quarkus:dev
./gradlew --console=plain quarkusDev
Lastly, open your browser and navigate to http://localhost:8080/fruits, you should see:
[{"id":2,"name":"Durian"},{"id":1,"name":"Kiwi"},{"id":4,"name":"Lychee"},{"id":3,"name":"Pomelo"}]
Prepared queries
The Reactive PostgreSQL Client can also prepare queries and take parameters that are replaced in the SQL statement at execution time:
client.preparedQuery("SELECT id, name FROM fruits WHERE id = $1").execute(Tuple.of(id))
For PostgreSQL, the SQL string can refer to parameters by position, using $1 , $2 , …etc.
Please refer to the Database Clients details section for other databases.
|
Similar to the simple query
method, preparedQuery
returns an instance of PreparedQuery<RowSet<Row>>
.
Equipped with this tooling, we are able to safely use an id
provided by the user to get the details of a particular 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 | Create a Tuple to hold the prepared query parameters. |
2 | Get an Iterator for the RowSet result. |
3 | Create a Fruit instance from the Row if an entity was found. |
And in the Jakarta REST resource:
@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 | Prepare a Jakarta REST response with either the Fruit instance if found or the 404 status code. |
2 | Build and send the response. |
The same logic applies when saving a 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"));
}
And in the web resource we handle the POST
request:
@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
A RowSet
does not only hold your data in memory, it also gives you some information about the data itself, such as:
-
the number of rows affected by the query (inserted/deleted/updated/retrieved depending on the query type),
-
the column names.
Let’s use this to support removal of fruits in the database:
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 | Inspect metadata to determine if a fruit has been actually deleted. |
And to handle the HTTP DELETE
method in the web resource:
@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());
}
With GET
, POST
and DELETE
methods implemented, we can now create a minimal web page to try the RESTful application out.
We will use jQuery to simplify interactions with the backend:
<!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 automatically serves static resources located under the META-INF/resources directory.
|
In the JavaScript code, we need a function to refresh the list of fruits when:
-
the page is loaded, or
-
a fruit is added, or
-
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 | The fruits parameter is not defined when the database is empty. |
All done! Navigate to http://localhost:8080/fruits.html and read/create/delete some fruits.
Database Clients details
Database | Extension name | Pool class name | Placeholders |
---|---|---|---|
IBM Db2 |
|
|
|
MariaDB/MySQL |
|
|
|
Microsoft SQL Server |
|
|
|
Oracle |
|
|
|
PostgreSQL |
|
|
|
事务
The reactive SQL clients support transactions.
A transaction is started with io.vertx.mutiny.sqlclient.SqlConnection#begin
and terminated with either io.vertx.mutiny.sqlclient.Transaction#commit
or io.vertx.mutiny.sqlclient.Transaction#rollback
.
All these operations are asynchronous:
-
connection.begin()
returns aUni<Transaction>
-
transaction.commit()
andtransaction.rollback()
returnUni<Void>
Managing transactions in the reactive programming world can be cumbersome.
Instead of writing repetitive and complex (thus error-prone!) code, you can use the io.vertx.mutiny.sqlclient.Pool#withTransaction
helper method.
The following snippet shows how to run 2 insertions in the same transaction:
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();
});
}
In this example, the transaction is automatically committed on success or rolled back on failure.
You can also create dependent actions as follows:
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
When executing batch queries, reactive SQL clients return a RowSet
that corresponds to the results of the first element in the batch.
To get the results of the following batch elements, you must invoke the RowSet#next
method until it returns null
.
Let’s say you want to update some rows and compute the total number of affected rows.
You must inspect each 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 | Compute the sum of RowSet#rowCount . |
2 | Invoke RowSet#next until it returns null . |
As another example, if you want to load all the rows you just inserted, you must concatenate the contents of each 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
The reactive SQL clients support defining several datasources.
A typical configuration with several datasources would look like:
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 | The default datasource - using PostgreSQL. |
2 | A named datasource called additional1 - using PostgreSQL. |
3 | A named datasource called additional2 - using MySQL. |
You can then inject the clients as follows:
@Inject (1)
PgPool defaultClient;
@Inject
@ReactiveDataSource("additional1") (2)
PgPool additional1Client;
@Inject
@ReactiveDataSource("additional2")
MySQLPool additional2Client;
1 | Injecting the client for the default datasource does not require anything special. |
2 | For a named datasource, you use the @ReactiveDataSource CDI qualifier with the datasource name as its value. |
UNIX Domain Socket connections
The PostgreSQL and MariaDB/MySQL clients can be configured to connect to the server through a UNIX domain socket.
First make sure that native transport support is enabled.
Then configure the database connection url. This step depends on the database type.
PostgreSQL
PostgreSQL domain socket paths have the following form: <directory>/.s.PGSQL.<port>
The database connection url must be configured so that:
-
the
host
is thedirectory
in the socket path -
the
port
is theport
in the socket path
Consider the following socket path: /var/run/postgresql/.s.PGSQL.5432
.
In application.properties
add:
quarkus.datasource.reactive.url=postgresql://:5432/quarkus_test?host=/var/run/postgresql
Load-balancing connections
The reactive PostgreSQL and MariaDB/MySQL clients support defining several connections.
A typical configuration with several connections would look like:
quarkus.datasource.reactive.url=postgresql://host1:5432/default,postgresql://host2:5432/default,postgresql://host3:5432/default
This can also be written with indexed property syntax:
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
Reactive datasources can be configured with an idle-timeout
.
It is the maximum time a connection remains unused in the pool before it is closed.
The idle-timeout is disabled by default.
|
For example, you could expire idle connections after 60 minutes:
quarkus.datasource.reactive.idle-timeout=PT60M
Pooled Connection max-lifetime
In addition to idle-timeout
, reactive datasources can also be configured with a max-lifetime
.
It is the maximum time a connection remains in the pool before it is closed and replaced as needed.
The max-lifetime
allows ensuring the pool has fresh connections with up-to-date configuration.
The max-lifetime is disabled by default but is an important configuration when using a credentials
provider that provides time limited credentials, like the Vault credentials provider.
|
For example, you could ensure connections are recycled after 60 minutes:
quarkus.datasource.reactive.max-lifetime=PT60M
Customizing pool creation
Sometimes, the database connection pool cannot be configured only by declaration.
For example, you might have to read a specific file only present in production, or retrieve configuration data from a proprietary configuration server.
In this case, you can customize pool creation by creating a class implementing an interface which depends on the target database:
Database | Pool creator class name |
---|---|
IBM Db2 |
|
MariaDB/MySQL |
|
Microsoft SQL Server |
|
Oracle |
|
PostgreSQL |
|
Here’s an example for 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
The PostgreSQL and MariaDB/MySQL clients support pipelining of queries at the connection level. The feature consists in sending multiple queries on the same database connection without waiting for the corresponding responses.
In some use cases, query pipelining can improve database access performance.
Here’s an example for 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);
}
}
The maximum number of pipelined queries is configured with the pipelining-limit
property:
# For PostgreSQL
quarkus.datasource.reactive.postgresql.pipelining-limit=256
# For MariaDB/MySQL
quarkus.datasource.reactive.mysql.pipelining-limit=256
By default, pipelining-limit
is set to 256.
配置参考
Common Datasource
Configuration property fixed at build time - All other configuration properties are overridable at runtime
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. If the datasource is not active, it won’t start with the application, and accessing the corresponding Datasource CDI bean will fail, meaning in particular that consumers of this datasource (e.g. Hibernate ORM persistence units) will fail to start unless they are inactive too. 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 path to a SQL script 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 |
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 |
|
Reactive Datasource
Configuration property fixed at build time - All other configuration properties are overridable at runtime
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> |
About the Duration format
To write duration values, use the standard You can also use a simplified format, starting with a number:
In other cases, the simplified format is translated to the
|
IBM Db2
Configuration property fixed at build time - All other configuration properties are overridable at runtime
Configuration property |
类型 |
默认 |
---|---|---|
类型 |
默认 |
|
Whether SSL/TLS is enabled. Environment variable: Show more |
boolean |
|
MariaDB/MySQL
Configuration property fixed at build time - All other configuration properties are overridable at runtime
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 |
boolean |
|
Microsoft SQL Server
Configuration property fixed at build time - All other configuration properties are overridable at runtime
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 fixed at build time - All other configuration properties are overridable at runtime
Configuration property |
类型 |
默认 |
---|---|---|
No configuration properties found. |
PostgreSQL
Configuration property fixed at build time - All other configuration properties are overridable at runtime
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 |
|