Exposed Gradle plugin
The Exposed Gradle plugin provides build-time tooling for working with Exposed-based database schemas.
Its primary feature is generating SQL migration scripts by comparing Exposed table definitions with an existing database schema.
Requirements
Kotlin 2.2 or later
Gradle 8.14 or later (Gradle installation guide)
JVM 11 or later
Docker (only required when using
Testcontainers)
Installation
To install the plugin, add it to the plugins block in your Gradle build script:
Generate migration scripts
To generate migration scripts based on the difference between your existing database schema and your Exposed table definitions, use the generateMigrations task:
Generated files are written to the configured output directory.
Integration with the build lifecycle
You can configure migration generation to run automatically during the Gradle build lifecycle.
For example, you can generate migrations before the build or the processResources tasks:
Configuration
Configure the plugin using the exposed.migrations block in your build.gradle.kts file.
At minimum, configure the following properties:
tablesPackageas the package name where Exposed table definitions are located.A database configuration or a
Testcontainersconfiguration.
Configure a database connection
To configure a database connection, set the databaseUrl, databaseUser, and databasePassword properties:
Configure Testcontainers
To configure a Testcontainers connection, set the testContainersImageName property:
Additional configuration
Optionally, you can configure the following properties for additional control over migration generation and file naming:
classpathClasspath scanned for Exposed table definitions.
Defaults to the project's runtime classpath.
fileDirectoryDirectory where migration scripts are stored.
Defaults to
"src/main/resources/db/migration".filePrefixPrefix used for migration script names.
Defaults to
"V".fileVersionFormatVersion format used for migration script names. For supported values, see version formats.
Defaults to a timestamp in the
yyyyMMddHHmmssformat.fileSeparatorSeparator used in migration script names.
Defaults to
"__".useUpperCaseDescriptionWhether the descriptive part of migration script names is converted to uppercase.
Defaults to
true.fileExtensionFile extension used for migration scripts.
Defaults to
".sql".
Example:
Version formats
The plugin supports the following VersionFormat values:
TIMESTAMP_ONLYInclude only the timestamp.
Example:
V20260417195521__CREATE_TABLE_USERS.sqlTIMESTAMP_WITHOUT_SECONDSInclude only the timestamp without seconds.
Example:
V202604171955__CREATE_TABLE_USERS.sqlMAJOR_TIMESTAMPInclude the major version and the timestamp.
Example:
V3_20260417195521__CREATE_TABLE_USERS.sqlMAJOR_TIMESTAMP_WITHOUT_SECONDSInclude the major version and the timestamp without seconds.
Example:
V3_202604171955__CREATE_TABLE_USERS.sqlMAJOR_MINORInclude the major and the minor version.
Example:
V3_1__CREATE_TABLE_USERS.sqlMAJOR_ONLYInclude 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:
For example:
The generated description (CREATE_TABLE_USERS) is derived from the generated SQL statement and typically follows this format:
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 TABLEstatement.If a sequence must be created before a table, the generated description still prefers the
CREATE TABLEstatement instead ofCREATE 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 --filename argument to the generateMigrations task:
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 Gradle plugin performs the following steps:
Starts a database container.
Applies existing migration scripts using Flyway.
Compares the resulting database schema with your Exposed table definitions.
Generates new migration scripts.
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 |
|
MariaDB |
|
PostgreSQL |
|
SQL Server |
|
Oracle | Images starting with |
Next steps
The Exposed Gradle 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:
Execute scripts manually using your database client.
Run scripts from the IntelliJ IDEA Database tool window.
Integrate migration execution into your CI/CD pipeline.
After applying the generated scripts, your database schema should match your current Exposed table definitions.