Using Flyway

Flyway is a popular database migration tool that is commonly used in JVM environments.

Quarkus provides first class support for using Flyway as will be explained in this guide.

Setting up support for Flyway

As shown in the Developing with Flyway section, to start using Flyway with your project, you just need to:

  • add your migrations to the src/main/resources/db/migration folder as you usually do with Flyway

  • activate the migrate-at-start option to migrate the schema automatically or inject the Flyway object and run your migration as you normally do

In your build file, add the following dependencies:

  • the Flyway extension

  • your JDBC driver extension (quarkus-jdbc-postgresql, quarkus-jdbc-h2, quarkus-jdbc-mariadb, …​)

  • the MariaDB/MySQL support is now in a separate dependency, MariaDB/MySQL users need to add the flyway-mysql dependency from now on.

  • the Microsoft SQL Server support is now in a separate dependency, Microsoft SQL Server users need to add the flyway-sqlserver dependency from now on.

pom.xml
<!-- Flyway specific dependencies -->
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-flyway</artifactId>
</dependency>

<!-- Flyway SQL Server specific dependencies -->
<dependency>
    <groupId>org.flywaydb</groupId>
    <artifactId>flyway-sqlserver</artifactId>
</dependency>

<!-- Flyway MariaDB/MySQL specific dependencies -->
<dependency>
    <groupId>org.flywaydb</groupId>
    <artifactId>flyway-mysql</artifactId>
</dependency>

<!-- JDBC driver dependencies -->
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-jdbc-postgresql</artifactId>
</dependency>
build.gradle
// Flyway specific dependencies
implementation("io.quarkus:quarkus-flyway")
// Flyway SQL Server specific dependencies
implementation("org.flywaydb:flyway-sqlserver")
// Flyway MariaDB/MySQL specific dependencies
implementation("org.flywaydb:flyway-mysql")
// JDBC driver dependencies
implementation("io.quarkus:quarkus-jdbc-postgresql")

Flyway support relies on the Quarkus datasource config. It can be customized for the default datasource as well as for every named datasource. First, you need to add the datasource config to the application.properties file in order to allow Flyway to manage the schema. Also, you can customize the Flyway behaviour by using the following properties:

Configuration property fixed at build time - All other configuration properties are overridable at runtime

Configuration property

Type

Default

Comma-separated list of locations to scan recursively for migrations. The location type is determined by its prefix. Unprefixed locations or locations starting with classpath: point to a package on the classpath and may contain both SQL and Java-based migrations. Locations starting with filesystem: point to a directory on the filesystem, may only contain SQL migrations and are only scanned recursively down non-hidden directories.

list of string

db/migration

Comma-separated list of fully qualified class names of Callback implementations to use to hook into the Flyway lifecycle. The org.flywaydb.core.api.callback.Callback sub-class must have a no-args constructor and must not be abstract. These classes must also not have any fields that hold state (unless that state is initialized in the constructor).

list of string

The maximum number of retries when attempting to connect to the database. After each failed attempt, Flyway will wait 1 second before attempting to connect again, up to the maximum number of times specified by connectRetries.

int

Sets the default schema managed by Flyway. This schema name is case-sensitive. If not specified, but schemas is, Flyway uses the first schema in that list. If that is also not specified, Flyway uses the default schema for the database connection. Consequences: - This schema will be the one containing the schema history table. - This schema will be the default for the database connection (provided the database supports this concept).

string

Comma-separated case-sensitive list of schemas managed by Flyway. The first schema in the list will be automatically set as the default one during the migration. It will also be the one containing the schema history table.

list of string

The name of Flyway’s schema history table. By default (single-schema mode) the schema history table is placed in the default schema for the connection provided by the datasource. When the flyway.schemas property is set (multi-schema mode), the schema history table is placed in the first schema of the list.

string

The file name prefix for versioned SQL migrations. Versioned SQL migrations have the following file name structure: prefixVERSIONseparatorDESCRIPTIONsuffix , which using the defaults translates to V1.1__My_description.sql

string

The file name prefix for repeatable SQL migrations. Repeatable SQL migrations have the following file name structure: prefixSeparatorDESCRIPTIONsuffix , which using the defaults translates to R__My_description.sql

string

true to execute Flyway clean command automatically when the application starts, false otherwise.

boolean

false

true to prevent Flyway clean operations, false otherwise.

boolean

false

true to execute Flyway automatically when the application starts, false otherwise.

boolean

false

Enable the creation of the history table if it does not exist already.

boolean

false

The initial baseline version.

string

The description to tag an existing schema with when executing baseline.

string

Whether to automatically call validate when performing a migration.

boolean

false

Allows migrations to be run "out of order".

boolean

false

Ignore missing migrations when reading the history table. When set to true migrations from older versions present in the history table but absent in the configured locations will be ignored (and logged as a warning), when false (the default) the validation step will fail.

boolean

false

Ignore future migrations when reading the history table. When set to true migrations from newer versions present in the history table but absent in the configured locations will be ignored (and logged as a warning), when false (the default) the validation step will fail.

boolean

false

Whether Flyway should attempt to create the schemas specified in the schemas property

boolean

true

Prefix of every placeholder (default: ${ )

string

Suffix of every placeholder (default: } )

string

The SQL statements to run to initialize a new database connection immediately after opening it.

string

Comma-separated list of locations to scan recursively for migrations. The location type is determined by its prefix. Unprefixed locations or locations starting with classpath: point to a package on the classpath and may contain both SQL and Java-based migrations. Locations starting with filesystem: point to a directory on the filesystem, may only contain SQL migrations and are only scanned recursively down non-hidden directories.

list of string

db/migration

Comma-separated list of fully qualified class names of Callback implementations to use to hook into the Flyway lifecycle. The org.flywaydb.core.api.callback.Callback sub-class must have a no-args constructor and must not be abstract. These classes must also not have any fields that hold state (unless that state is initialized in the constructor).

list of string

Sets the placeholders to replace in SQL migration scripts.

Map<String,String>

The maximum number of retries when attempting to connect to the database. After each failed attempt, Flyway will wait 1 second before attempting to connect again, up to the maximum number of times specified by connectRetries.

int

Sets the default schema managed by Flyway. This schema name is case-sensitive. If not specified, but schemas is, Flyway uses the first schema in that list. If that is also not specified, Flyway uses the default schema for the database connection. Consequences: - This schema will be the one containing the schema history table. - This schema will be the default for the database connection (provided the database supports this concept).

string

Comma-separated case-sensitive list of schemas managed by Flyway. The first schema in the list will be automatically set as the default one during the migration. It will also be the one containing the schema history table.

list of string

The name of Flyway’s schema history table. By default (single-schema mode) the schema history table is placed in the default schema for the connection provided by the datasource. When the flyway.schemas property is set (multi-schema mode), the schema history table is placed in the first schema of the list.

string

The file name prefix for versioned SQL migrations. Versioned SQL migrations have the following file name structure: prefixVERSIONseparatorDESCRIPTIONsuffix , which using the defaults translates to V1.1__My_description.sql

string

The file name prefix for repeatable SQL migrations. Repeatable SQL migrations have the following file name structure: prefixSeparatorDESCRIPTIONsuffix , which using the defaults translates to R__My_description.sql

string

true to execute Flyway clean command automatically when the application starts, false otherwise.

boolean

false

true to prevent Flyway clean operations, false otherwise.

boolean

false

true to execute Flyway automatically when the application starts, false otherwise.

boolean

false

Enable the creation of the history table if it does not exist already.

boolean

false

string

The description to tag an existing schema with when executing baseline.

string

Whether to automatically call validate when performing a migration.

boolean

false

Allows migrations to be run "out of order".

boolean

false

Ignore missing migrations when reading the history table. When set to true migrations from older versions present in the history table but absent in the configured locations will be ignored (and logged as a warning), when false (the default) the validation step will fail.

boolean

false

Ignore future migrations when reading the history table. When set to true migrations from newer versions present in the history table but absent in the configured locations will be ignored (and logged as a warning), when false (the default) the validation step will fail.

boolean

false

Sets the placeholders to replace in SQL migration scripts.

Map<String,String>

Whether Flyway should attempt to create the schemas specified in the schemas property

boolean

true

Prefix of every placeholder (default: ${ )

string

Suffix of every placeholder (default: } )

string

The SQL statements to run to initialize a new database connection immediately after opening it.

string

Developing with Flyway

The following is an example for the application.properties file:

# configure your datasource
quarkus.datasource.db-kind=postgresql
quarkus.datasource.username=sarah
quarkus.datasource.password=connor
quarkus.datasource.jdbc.url=jdbc:postgresql://localhost:5432/mydatabase

# Run Flyway migrations automatically
quarkus.flyway.migrate-at-start=true

# More Flyway configuration options
# quarkus.flyway.baseline-on-migrate=true
# quarkus.flyway.baseline-version=1.0.0
# quarkus.flyway.baseline-description=Initial version
# quarkus.flyway.connect-retries=10
# quarkus.flyway.schemas=TEST_SCHEMA
# quarkus.flyway.table=flyway_quarkus_history
# quarkus.flyway.locations=db/location1,db/location2
# quarkus.flyway.sql-migration-prefix=X
# quarkus.flyway.repeatable-sql-migration-prefix=K

Add a SQL migration to the default folder following the Flyway naming conventions: src/main/resources/db/migration/V1.0.0__Quarkus.sql

CREATE TABLE quarkus
(
  id   INT,
  name VARCHAR(20)
);
INSERT INTO quarkus(id, name)
VALUES (1, 'QUARKED');

Now you can start your application and Quarkus will run the Flyway’s migrate method according to your config.

With quarkus.flyway.migrate-at-start=true, as in the example above, Quarkus will execute the Flyway migration as part of the application startup.
@ApplicationScoped
public class MigrationService {
    // You can Inject the object if you want to use it manually
    @Inject
    Flyway flyway; (1)

    public void checkMigration() {
        // This will print 1.0.0
        System.out.println(flyway.info().current().getVersion().toString());
    }
}
1 Inject the Flyway object if you want to use it directly
In dev-mode Quarkus will automatically restart the application if any of the existing migration scripts get modified. If you want to take advantage of this while developing and testing new migration scripts, you will want to set %dev.quarkus.flyway.clean-at-start=true, so that Flyway actually runs the modified migration.

Multiple datasources

Flyway can be configured for multiple datasources. The Flyway properties are prefixed exactly the same way as the named datasources, for example:

quarkus.datasource.db-kind=h2
quarkus.datasource.username=username-default
quarkus.datasource.jdbc.url=jdbc:h2:tcp://localhost/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:tcp://localhost/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:tcp://localhost/mem:inventory
quarkus.datasource.inventory.jdbc.max-size=12

# Flyway configuration for the default datasource
quarkus.flyway.schemas=DEFAULT_TEST_SCHEMA
quarkus.flyway.locations=db/default/location1,db/default/location2
quarkus.flyway.migrate-at-start=true

# Flyway configuration for the "users" datasource
quarkus.flyway.users.schemas=USERS_TEST_SCHEMA
quarkus.flyway.users.locations=db/users/location1,db/users/location2
quarkus.flyway.users.migrate-at-start=true

# Flyway configuration for the "inventory" datasource
quarkus.flyway.inventory.schemas=INVENTORY_TEST_SCHEMA
quarkus.flyway.inventory.locations=db/inventory/location1,db/inventory/location2
quarkus.flyway.inventory.migrate-at-start=true

Notice there’s an extra bit in the key. The syntax is as follows: quarkus.flyway.[optional name.][datasource property].

Without configuration, Flyway is set up for every datasource using the default settings.

Using the Flyway object

In case you are interested in using the Flyway object directly, you can inject it as follows:

@ApplicationScoped
public class MigrationService {
    // You can Inject the object if you want to use it manually
    @Inject
    Flyway flyway; (1)

    @Inject
    @FlywayDataSource("inventory") (2)
    Flyway flywayForInventory;

    @Inject
    @Named("flyway_users") (3)
    Flyway flywayForUsers;

    public void checkMigration() {
        // Use the flyway instance manually
        flyway.clean(); (4)
        flyway.migrate();
        // This will print 1.0.0
        System.out.println(flyway.info().current().getVersion().toString());
    }
}
1 Inject the Flyway object if you want to use it directly
2 Inject Flyway for named datasources using the Quarkus FlywayDataSource qualifier
3 Inject Flyway for named datasources
4 Use the Flyway instance directly

Flyway and Hibernate ORM

When using Flyway together with Hibernate ORM, you can use the Dev UI to generate the initial schema creation script.

You can find more information about this feature in the Hibernate ORM guide.