Exposed 1.4.0 Help

Exposed Maven plugin

The Exposed Maven plugin provides build-time tooling for working with Exposed-based database schemas in Maven projects.

Its primary feature is generating SQL migration scripts by comparing Exposed table definitions with an existing database schema.

Requirements

Installation

To install the plugin, add it to the <build><plugins> section of your pom.xml file:

<build> <plugins> <plugin> <groupId>org.jetbrains.exposed.plugin</groupId> <artifactId>exposed-maven-plugin</artifactId> <version>1.4.0</version> </plugin> </plugins> </build>

Generate migration scripts

To generate migration scripts based on the difference between your existing database schema and your Exposed table definitions, invoke the generate-migration goal:

mvn exposed:generate-migrations

Generated files are written to the configured output directory.

Integration with the build lifecycle

You can bind migration generation to a Maven lifecycle phase by adding an <executions> block to the plugin configuration. For example, to generate migrations during the process-classes phase:

<plugin> <groupId>org.jetbrains.exposed.plugin</groupId> <artifactId>exposed-maven-plugin</artifactId> <version>1.4.0</version> <executions> <execution> <id>generate-migrations</id> <phase>process-classes</phase> <goals> <goal>generate-migrations</goal> </goals> </execution> </executions> </plugin>

Configuration

Configure the plugin using the <configuration> block inside the plugin entry in your pom.xml file.

At minimum, configure the following parameters:

  • tablesPackage as the package name where Exposed table definitions are located.

  • A database configuration or a Testcontainers configuration.

Configure a database connection

To configure a database connection, set the databaseUrl, databaseUser, and databasePassword parameters:

<plugin> <groupId>org.jetbrains.exposed.plugin</groupId> <artifactId>exposed-maven-plugin</artifactId> <version>1.4.0</version> <configuration> <tablesPackage>com.example.db.tables</tablesPackage> <databaseUrl>jdbc:postgresql://localhost:5432/mydb</databaseUrl> <databaseUser>postgres</databaseUser> <databasePassword>password</databasePassword> </configuration> </plugin>

Configure Testcontainers

To configure a Testcontainers connection, set the testContainersImageName parameter:

<plugin> <groupId>org.jetbrains.exposed.plugin</groupId> <artifactId>exposed-maven-plugin</artifactId> <version>1.4.0</version> <configuration> <tablesPackage>com.example.db.tables</tablesPackage> <testContainersImageName>postgres:latest</testContainersImageName> </configuration> </plugin>

Override parameters from the command line

To override any plugin parameter on the command line, use the matching exposed.migrations.<name> system property:

mvn exposed:generate-migrations \ -Dexposed.migrations.tablesPackage=com.example.db.tables \ -Dexposed.migrations.databaseUrl=jdbc:postgresql://localhost:5432/mydb \ -Dexposed.migrations.databaseUser=postgres \ -Dexposed.migrations.databasePassword=password

Additional configuration

Optionally, you can configure the following parameters for additional control over migration generation and file naming:

fileDirectory

Directory where migration scripts are stored.

Defaults to src/main/resources/db/migration under the project base directory.

filePrefix

Prefix used for migration script names.

Defaults to "V".

fileVersionFormat

Version format used for migration script names. For supported values, see version formats.

Defaults to a timestamp in the yyyyMMddHHmmss format.

fileSeparator

Separator used in migration script names.

Defaults to "__".

useUpperCaseDescription

Whether the descriptive part of migration script names is converted to uppercase.

Defaults to true.

fileExtension

File extension used for migration scripts.

Defaults to ".sql".

Example:

<plugin> <groupId>org.jetbrains.exposed.plugin</groupId> <artifactId>exposed-maven-plugin</artifactId> <version>1.4.0</version> <configuration> <tablesPackage>com.example.db.tables</tablesPackage> <databaseUrl>jdbc:postgresql://localhost:5432/mydb</databaseUrl> <databaseUser>postgres</databaseUser> <databasePassword>password</databasePassword> <fileDirectory>${project.basedir}/src/main/resources/db/migration</fileDirectory> <filePrefix>V</filePrefix> <fileVersionFormat>TIMESTAMP_ONLY</fileVersionFormat> <fileSeparator>__</fileSeparator> <useUpperCaseDescription>true</useUpperCaseDescription> <fileExtension>.sql</fileExtension> </configuration> </plugin>

Version formats

The plugin supports the following fileVersionFormat values:

TIMESTAMP_ONLY

Include only the timestamp.

Example: V20260417195521__CREATE_TABLE_USERS.sql

TIMESTAMP_WITHOUT_SECONDS

Include only the timestamp without seconds.

Example: V202604171955__CREATE_TABLE_USERS.sql

MAJOR_TIMESTAMP

Include the major version and the timestamp.

Example: V3_20260417195521__CREATE_TABLE_USERS.sql

MAJOR_TIMESTAMP_WITHOUT_SECONDS

Include the major version and the timestamp without seconds.

Example: V3_202604171955__CREATE_TABLE_USERS.sql

MAJOR_MINOR

Include the major and the minor version.

Example: V3_1__CREATE_TABLE_USERS.sql

MAJOR_ONLY

Include the major version only.

Example: V3__CREATE_TABLE_USERS.sql

For version formats that include a major version, the plugin scans the configured fileDirectory to determine the next available version. If the directory is empty, or if no compatible migration files are found, numbering starts at 1.

File naming

By default, migration scripts use the following naming pattern:

<prefix><version><separator><description><extension>

For example:

V20260417195521__CREATE_TABLE_USERS.sql

The generated description (CREATE_TABLE_USERS) is derived from the generated SQL statement and typically follows this format:

<OPERATION>_<OBJECT>_<IDENTIFIER>_<EXTRA>

When a migration contains multiple SQL statements, the description is usually derived from the first significant statement.

  • A migration that creates two related tables typically uses the description of the first CREATE TABLE statement.

  • If a sequence must be created before a table, the generated description still prefers the CREATE TABLE statement instead of CREATE SEQUENCE.

If the plugin cannot derive a standard description, it falls back to a generic name, such as CUSTOM_STATEMENT_12345.

Override the generated filename

You can override the generated filename by passing the exposed.migrations.filename system property to the generate-migration goal:

mvn exposed:generate-migrations -Dexpose.migrations.filename=V0__initialize_schema.sql

Using Testcontainers

Testcontainers is a Java library that lets you run temporary Docker containers during tests or build tasks. You can use Testcontainers to start a disposable database instance automatically while generating migration scripts.

Testcontainers workflow

When using Testcontainers, the Exposed Maven plugin performs the following steps:

  1. Starts a database container.

  2. Applies existing migration scripts using Flyway.

  3. Compares the resulting database schema with your Exposed table definitions.

  4. Generates new migration scripts.

  5. Stops the container.

If the configured migration directory contains existing migration scripts, the plugin applies them using Flyway before generating new migrations.

This ensures that newly generated migration scripts are based on the latest schema state, including changes introduced by previous migrations.

Supported databases

The plugin supports the following database container images:

Database

Container images

MySQL

mysql, mysql:latest, or other tags

MariaDB

mariadb, mariadb:latest, or other tags

PostgreSQL

postgres, postgres:latest, or other tags

SQL Server

mcr.microsoft.com/mssql/server, mcr.microsoft.com/mssql/server:2025-latest, or other tags

Oracle

Images starting with container-registry.oracle.com/, gvenzl/oracle- or oracle/

Next steps

The Exposed Maven plugin generates migration scripts, but it does not apply them to your database automatically.

After generating migration scripts, review and apply them using your existing database migration workflow. For example, you can:

After applying the generated scripts, your database schema should match your current Exposed table definitions.

05 August 2026