Many projects that use data require connections to a relational database.
The usual way of obtaining connections to a database is to use a datasource and configure a JDBC driver. But you might also prefer using a reactive driver to connect to your database in a reactive way.
Quarkus has you covered either way:
Both are configured via unified and flexible configuration.
Note
|
Agroal is a modern, light weight connection pool implementation designed for very high performance and scalability, and features first class integration with the other components in Quarkus, such as security, transaction management components, health, and metrics. |
This guide will explain how to:
-
configure a datasource, or multiple datasources
-
how to obtain a reference to those datasources in code
-
which pool tuning configuration properties are available
This guide is mainly about datasource configuration. If you want more details about how to consume and make use of a reactive datasource, please refer to the Reactive SQL clients guide.
This is a quick introduction to datasource configuration. If you want a better understanding of how all this works, this guide has a lot more information in the subsequent paragraphs.
When testing or running in dev mode Quarkus can even provide you with a zero config database out of the box, a feature we refer to as Dev Services. Depending on your database type you may need docker installed in order to use this feature. Dev Services is supported for the following open source databases:
-
Postgresql (container)
-
MySQL (container)
-
MariaDB (container)
-
H2 (in-process)
-
Apache Derby (in-process)
-
DB2 (container) (requires license acceptance)
-
MSSQL (container) (requires license acceptance)
If you want to use Dev Services then all you need to do is include the relevant extension for the type of database you want (either reactive or JDBC, or both), and don’t configure a database URL, username and password, Quarkus will provide the database and you can just start coding without worrying about config.
If you are using a proprietary database such as DB2 or MSSQL you will need to accept the license agreement. To do this
create a src/main/resources/container-license-acceptance.txt
files in your project and add a line with the image
name and tag of the database. By default Quarkus uses the default image for the current version of Testcontainers, if
you attempt to start Quarkus the resulting failure will tell you the exact image name in use for you to add to the
file.
An example file is shown below:
ibmcom/db2:11.5.0.0a mcr.microsoft.com/mssql/server:2017-CU12
Note
|
All services based on containers are run using Testcontainers but Quarkus is not using the Testcontainers JDBC driver. Thus, even though extra JDBC URL properties can be set in your Quarkus can support specific properties sent to the container itself though and,
typically, this is the case for Overriding the MariaDB/MySQL configuration would be done as follows: quarkus.datasource.devservices.container-properties.TC_MY_CNF=testcontainers/mysql-conf This support is database specific and needs to be implemented in each dev service specifically. |
Add the agroal
extension plus one of jdbc-db2
, jdbc-derby
, jdbc-h2
, jdbc-mariadb
, jdbc-mssql
, jdbc-mysql
, jdbc-oracle
or jdbc-postgresql
.
Then configure your datasource:
quarkus.datasource.db-kind=postgresql (1)
quarkus.datasource.username=<your username>
quarkus.datasource.password=<your password>
quarkus.datasource.jdbc.url=jdbc:postgresql://localhost:5432/hibernate_orm_test
quarkus.datasource.jdbc.max-size=16
-
If you only have a single JDBC extension, or you are running tests and only have a single test scoped JDBC extension installed then this is optional. If there is only one possible extension we assume this is the correct one, and if a driver has been added with test scope then we assume that this should be used in testing.
Add the correct reactive extension for the database you are using: reactive-pg-client
, reactive-mssql-client
, reactive-mysql-client
, or reactive-db2-client
.
Then configure your reactive datasource:
quarkus.datasource.db-kind=postgresql (1)
quarkus.datasource.username=<your username>
quarkus.datasource.password=<your password>
quarkus.datasource.reactive.url=postgresql:///your_database
quarkus.datasource.reactive.max-size=20
-
As specified above this is optional.
A datasource can be either a JDBC datasource, a reactive one or both. It all depends on how you configure it and which extensions you added to your project.
To define a datasource, start with the following (note that this is only required if you have more than one database type installed):
quarkus.datasource.db-kind=h2
The database kind defines which type of database you will connect to.
We currently include these built-in database kinds:
-
DB2:
db2
-
Derby:
derby
-
H2:
h2
-
MariaDB:
mariadb
-
Microsoft SQL Server:
mssql
-
MySQL:
mysql
-
Oracle:
oracle
-
PostgreSQL:
postgresql
,pgsql
orpg
Giving Quarkus the database kind you are targeting will facilitate configuration.
By using a JDBC driver extension and setting the kind in the configuration,
Quarkus resolves the JDBC driver automatically,
so you don’t need to configure it yourself.
If you want to use a database kind that is not part of the built-in ones, use other
and define the JDBC driver explicitly.
Note
|
You can use any JDBC driver in a Quarkus app in JVM mode (see Using other databases). It is unlikely that it will work when compiling your application to a native executable though. If you plan to make a native executable, we recommend you use the existing JDBC Quarkus extensions (or contribute one for your driver). |
There is a good chance you will need to define some credentials to access your database.
This is done by configuring the following properties:
quarkus.datasource.username=<your username>
quarkus.datasource.password=<your password>
You can also retrieve the password from Vault by using a credential provider for your datasource.
Once you have defined the database kind and the credentials, you are ready to configure either a JDBC datasource, a reactive one, or both.
JDBC is the most common database connection pattern. You typically need a JDBC datasource when using Hibernate ORM.
First, you will need to add the quarkus-agroal
dependency to your project.
You can add it using a simple Maven command:
./mvnw quarkus:add-extension -Dextensions="agroal"
Tip
|
Agroal comes as a transitive dependency of the Hibernate ORM extension so if you are using Hibernate ORM, you don’t need to add the Agroal extension dependency explicitly. |
You will also need to choose, and add, the Quarkus extension for your relational database driver.
Quarkus provides driver extensions for:
-
DB2 -
jdbc-db2
-
Derby -
jdbc-derby
-
H2 -
jdbc-h2
-
MariaDB -
jdbc-mariadb
-
Microsoft SQL Server -
jdbc-mssql
-
MySQL -
jdbc-mysql
-
Oracle -
jdbc-oracle
-
PostgreSQL -
jdbc-postgresql
See Use a database with no built-in extension or with a different driver if you want to use a JDBC driver for another database.
Note
|
The H2 and Derby databases can normally be configured to run in "embedded mode"; the extension does not support compiling the embedded database engine into native executables. Read Testing with in-memory databases (below) for suggestions regarding integration testing. |
As usual, you can install the extension using add-extension
.
To install the PostgreSQL driver dependency for instance, run the following command:
./mvnw quarkus:add-extension -Dextensions="jdbc-postgresql"
Configuring your JDBC connection is easy, the only mandatory property is the JDBC URL.
quarkus.datasource.jdbc.url=jdbc:postgresql://localhost:5432/hibernate_orm_test
Note
|
Note the |
Tip
|
For more information about the JDBC URL format, please refer to the JDBC url reference section. |
When using one of the built-in datasource kinds, the JDBC driver is resolved automatically to the following values:
Database kind | JDBC driver | XA driver |
---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Tip
|
As previously stated, most of the time, this automatic resolution will suit you and you won’t need to configure the driver. |
You can use a specific driver if you need to (for instance for using the OpenTracing driver) or if you want to use a database for which Quarkus does not have a built-in JDBC driver extension.
Without an extension, the driver will work fine in any Quarkus app running in JVM mode. It is unlikely that it will work when compiling your application to a native executable though. If you plan to make a native executable, we recommend you use the existing JDBC Quarkus extensions (or contribute one for your driver).
Here is how you would use the OpenTracing driver:
quarkus.datasource.jdbc.driver=io.opentracing.contrib.jdbc.TracingDriver
Here is how you would define access to a database with no built-in support (in JVM mode):
quarkus.datasource.db-kind=other
quarkus.datasource.jdbc.driver=oracle.jdbc.driver.OracleDriver
quarkus.datasource.jdbc.url=jdbc:oracle:thin:@192.168.1.12:1521/ORCL_SVC
quarkus.datasource.username=scott
quarkus.datasource.password=tiger
You can configure a lot more things, for instance the size of the connection pool.
Please refer to the JDBC configuration reference for all the details about the JDBC configuration knobs.
If you are using Hibernate ORM, the datasource will be consumed automatically.
If for whatever reason, access to the datasource is needed in code, it can be obtained as any other bean in the following manner:
@Inject
AgroalDataSource defaultDataSource;
In the above example, the type is AgroalDataSource
which is a subtype of javax.sql.DataSource
.
Because of this, you can also use javax.sql.DataSource
as the injected type.
If you prefer using a reactive datasource, Quarkus offers DB2, MySQL/MariaDB, and PostgreSQL reactive clients.
Depending on which database you want to use, add the corresponding extension:
-
DB2:
quarkus-reactive-db2-client
-
MySQL/MariaDB:
quarkus-reactive-mysql-client
-
PostgreSQL:
quarkus-reactive-pg-client
The installed extension must be consistent with the quarkus.datasource.db-kind
you define in your datasource configuration.
Once the driver is there, you just need to configure the connection URL.
Optionally, but highly recommended, you should define a proper size for your connection pool.
quarkus.datasource.reactive.url=postgresql:///your_database
quarkus.datasource.reactive.max-size=20
By default, if you include both a JDBC extension (+ Agroal) and a reactive datasource extension handling the given database kind, both will be created.
If you want to disable the JDBC datasource explicitly, use:
quarkus.datasource.jdbc=false
If you want to disable the reactive datasource explicitly, use:
quarkus.datasource.reactive=false
Tip
|
Most of the time, the configuration above won’t be necessary as either a JDBC driver or a reactive datasource extension will be present and not both. |
For now, multiple datasources are only supported for JDBC and the Agroal extension. So it is not currently possible to create multiple reactive datasources.
Note
|
The Hibernate ORM extension supports defining several persistence units using configuration properties. For each persistence unit, you can point to the datasource of your choice. |
Defining multiple datasources works exactly the same way as defining a single datasource, with one important change: you define a name.
In the following example, you have 3 different datasources:
-
The default one,
-
A datasource named
users
, -
A datasource named
inventory
,
each with its own configuration.
quarkus.datasource.db-kind=h2
quarkus.datasource.username=username-default
quarkus.datasource.jdbc.url=jdbc:h2:mem:default
quarkus.datasource.jdbc.max-size=13
quarkus.datasource.users.db-kind=h2
quarkus.datasource.users.username=username1
quarkus.datasource.users.jdbc.url=jdbc:h2:mem:users
quarkus.datasource.users.jdbc.max-size=11
quarkus.datasource.inventory.db-kind=h2
quarkus.datasource.inventory.username=username2
quarkus.datasource.inventory.jdbc.url=jdbc:h2:mem:inventory
quarkus.datasource.inventory.jdbc.max-size=12
Notice there is an extra bit in the key.
The syntax is as follows: quarkus.datasource.[optional name.][datasource property]
.
Note
|
Even when only one database extension is installed, named databases need to specify at least one build time
property so that Quarkus knows they exist. Generally this will be the db-kind property, although you can also
specify Dev Services properties to create named datasources (covered later in this guide).
|
When using multiple datasources, each DataSource
also has the io.quarkus.agroal.DataSource
qualifier with the name of the datasource as the value.
Using the above properties to configure three different datasources, you can also inject each one as follows:
@Inject
AgroalDataSource defaultDataSource;
@Inject
@DataSource("users")
AgroalDataSource usersDataSource;
@Inject
@DataSource("inventory")
AgroalDataSource inventoryDataSource;
If you are using the quarkus-smallrye-health
extension, the quarkus-agroal
and reactive client extensions will automatically add a readiness health check
to validate the datasource.
When you access the /q/health/ready
endpoint of your application you will have information about the datasource validation status.
If you have multiple datasources, all datasources will be checked and the status will be DOWN
as soon as there is one datasource validation failure.
This behavior can be disabled via the property quarkus.datasource.health.enabled
.
If you are using the quarkus-micrometer
or quarkus-smallrye-metrics
extension, quarkus-agroal
can expose some data source metrics on the
/q/metrics
endpoint. This can be turned on by setting the property quarkus.datasource.metrics.enabled
to true.
For the exposed metrics to contain any actual values, it is necessary that metric collection is enabled internally
by Agroal mechanisms. By default, this metric collection mechanism gets turned on for all data sources if a metrics extension
is present and metrics for the Agroal extension are enabled. If you want to disable metrics for a particular data source,
this can be done by setting quarkus.datasource.jdbc.enable-metrics
to false
(or quarkus.datasource.<datasource name>.jdbc.enable-metrics
for a named datasource).
This disables collecting the metrics as well as exposing them in the /q/metrics
endpoint,
because it does not make sense to expose metrics if the mechanism to collect them is disabled.
Conversely, setting quarkus.datasource.jdbc.enable-metrics
to true
(or quarkus.datasource.<datasource name>.jdbc.enable-metrics
for a named datasource) explicitly can be used to enable collection of metrics even if
a metrics extension is not in use.
This can be useful if you need to access the collected metrics programmatically.
They are available after calling dataSource.getMetrics()
on an injected AgroalDataSource
instance. If collection of metrics is disabled
for this data source, all values will be zero.
If the Narayana JTA extension is also available, integration is automatic.
You can override this by setting the transactions
configuration property - see the Configuration Reference below.
As mentioned above Quarkus supports a feature called Dev Services that allows you to create datasources without any config. If you have a database extension that supports it and no config is provided, Quarkus will automatically start a database (either using Testcontainers, or by starting a Java DB in process), and automatically configure a connection to this database.
Production databases need to be configured as normal, so if you want to include a production database config in your
application.properties and continue to use Dev Services we recommend that you use the %prod.
profile to define your
database settings.
Dev Services supports the following config options:
When using Dev Services the default datasource will always be created, but to specify a named datasource you need to have
at least one build time property so Quarkus knows to create the datasource. In general you will usually either specify
the db-kind
property, or explicitly enable DevDb: quarkus.datasource."name".devservices.enabled=true
.
Some databases like H2 and Derby are commonly used in "embedded mode" as a facility to run quick integration tests.
Our suggestion is to use the real database you intend to use in production; container technologies made this simple enough so you no longer have an excuse. Still, there are sometimes good reasons to also want the ability to run quick integration tests using the JVM powered databases, so this is possible as well.
It is important to remember that when configuring H2 (or Derby) to use the embedded engine, this will work as usual in JVM mode but such an application will not compile into a native executable, as the Quarkus extensions only cover for making the JDBC client code compatible with the native compilation step: embedding the whole database engine into a native executable is currently not implemented.
If you plan to run such integration tests in the JVM exclusively, it will of course work as usual.
If you want the ability to run such integration test in both JVM and/or native executables, we have some cool helpers for you: just add either @QuarkusTestResource(H2DatabaseTestResource.class)
or @QuarkusTestResource(DerbyDatabaseTestResource.class)
on any class in your integration tests, this will make sure the test suite starts (and stops) the embedded database into a separate process as necessary to run your tests.
These additional helpers are provided by the artifacts having Maven coordinates io.quarkus:quarkus-test-h2
and io.quarkus:quarkus-test-derby
, respectively for H2 and Derby.
Follows an example for H2:
package my.app.integrationtests.db;
import io.quarkus.test.common.QuarkusTestResource;
import io.quarkus.test.h2.H2DatabaseTestResource;
@QuarkusTestResource(H2DatabaseTestResource.class)
public class TestResources {
}
This will allow you to test your application even when it’s compiled into a native executable, while the database will run in the JVM as usual.
Connect to it using:
quarkus.datasource.db-kind=h2
quarkus.datasource.jdbc.url=jdbc:h2:mem:test
Each of the supported databases contains different JDBC URL configuration options. Going into each of those options is beyond the scope of this document, but the following section gives an overview of each database URL and a link to the official documentation.
jdbc:h2:{ {.|mem:}[name] | [file:]fileName | {tcp|ssl}:[//]server[:port][,server2[:port]]/name }[;key=value…]
- Example
-
jdbc:h2:tcp://localhost/~/test
,jdbc:h2:mem:myDB
H2 is an embedded database. It can run as a server, based on a file, or live completely in memory. All of these options are available as listed above. You can find more information at the official documentation.
PostgreSQL only runs as a server, as do the rest of the databases below. As such, you must specify connection details, or use the defaults.
jdbc:postgresql:[//][host][:port][/database][?key=value…]
- Example
-
jdbc:postgresql://localhost/test
Defaults for the different parts are as follows:
host
-
localhost
port
-
5432
database
-
same name as the username
The official documentation go into more detail and list optional parameters as well.
jdbc:db2://<serverName>[:<portNumber>]/<databaseName>[:<key1>=<value>;[<key2>=<value2>;]]
- Example
-
jdbc:db2://localhost:50000/MYDB:user=dbadm;password=dbadm;
See the official documentation for more detail on URL syntax and additional supported options.
jdbc:mariadb:[replication:|failover:|sequential:|aurora:]//<hostDescription>[,<hostDescription>…]/[database][?<key1>=<value1>[&<key2>=<value2>]]
hostDescription:: <host>[:<portnumber>] or address=(host=<host>)[(port=<portnumber>)][(type=(master|slave))]
- Example
-
jdbc:mariadb://localhost:3306/test
You can find more information about this feature and others detailed in the official documentation.
jdbc:mysql:[replication:|failover:|sequential:|aurora:]//<hostDescription>[,<hostDescription>…]/[database][?<key1>=<value1>[&<key2>=<value2>]]
hostDescription:: <host>[:<portnumber>] or address=(host=<host>)[(port=<portnumber>)][(type=(master|slave))]
- Example
-
jdbc:mysql://localhost:3306/test
You can find more information about this feature and others detailed in the official documentation.
When compiling a Quarkus application to native-image, the MySQL support for JMX and Oracle Cloud Infrastructure (OCI) integrations are disabled as they are not compatible with GraalVM native-images. The lack of JMX support is a natural consequence of running in native and is unlikely to be resolved. The integration with OCI could be resolved, if you need it we suggest opening a support request with the MySQL Connector/J maintainers.
Microsoft SQL Server takes a connection URL in the following form:
jdbc:sqlserver://[serverName[\instanceName][:portNumber]][;property=value[;property=value]]
- Example
-
jdbc:sqlserver://localhost:1433;databaseName=AdventureWorks
The Microsoft SQL Server JDBC driver works essentially the same as the others. More details can be found in the official documentation.
jdbc:derby:[//serverName[:portNumber]/][memory:]databaseName[;property=value[;property=value]]
- Example
-
jdbc:derby://localhost:1527/myDB
,jdbc:derby:memory:myDB;create=true
Derby is an embedded database. It can run as a server, based on a file, or live completely in memory. All of these options are available as listed above. You can find more information at the official documentation.