I have a modular Spring Boot
project. As a database schema manager, I would like to use Flyway
.
As already stated, the project is modular. This is, because there will be different configurations which use different modules. This means, that I would like to pack everything that is related to a module to it's specific project. With Flyway
this seems not that simple.
What I ideally imagine:
ApplicationA
|
|_Module1
| |
| |_db/migration
| |
| |_V1__InitModule1Tables
| |_V2__MigrateSomeTable
|
|_Module2
|
|_db/migration
|
|_V1__InitModule2Tables
|_V2__MigrateSomeTable
Each module defines its own flyaway script independently, as they don't know from each others existence anyway. Each module would obviously need his own flyway history table inside of the share db. This way the whole system is decoupled and configuring the next application ApplicationB
with Module1
and Module3
won't be a hassle.
Well I didn't find any configuration possibility for Flyway
to reach this solution.
Doing something like this within each module is obviously a bad idea, as the the initialization/execution order of beans is rather random, leading in not having the tables created when I need them for other configurations. Also it seems messy.
@Configuration
public class Module1Config {
@Autowired
public void flyway(DataSource dataSource) {
Flyway flyway = new Flyway();
flyway.setBaselineOnMigrate(true);
flyway.setTable(flyway.getTable() + "-module1");
flyway.setDataSource(dataSource);
flyway.migrate();
}
}
I don't think that I'm the first person which tries to achieve that. How could I reach the desired modular Flyway
configuration?
The following solution, which works in the way as the duplicate topic suggests, is working for me:
I crated a configuration template in my base
module which is used by any other module as it provides global functions as logging and journaling.
public abstract class FlywayConfig {
private final String moduleName;
public FlywayConfig(String moduleName) {
this.moduleName = moduleName;
}
private final String baseScriptLocation = "classpath:db.migration.";
@Autowired
public void migrate(DataSource dataSource) {
Flyway flyway = new Flyway();
flyway.setDataSource(dataSource);
flyway.setSchemas(moduleName.toUpperCase());
flyway.setLocations(baseScriptLocation + moduleName.toLowerCase());
flyway.migrate();
}
}
In each module, I simply extend this configuration class
@Configuration
public class BaseConfig extends FlywayConfig {
public static final String MODULE_NAME = "base";
public BaseConfig() {
super(MODULE_NAME);
}
}
Whereas I save my flyway scripts in db.migration.*MODULE_NAME*
Supported databases are Oracle, SQL Server (including Amazon RDS and Azure SQL Database), Azure Synapse (Formerly Data Warehouse), DB2, MySQL (including Amazon RDS, Azure Database & Google Cloud SQL), Aurora MySQL, MariaDB, Percona XtraDB Cluster, TestContainers, PostgreSQL (including Amazon RDS, Azure Database, Google ...
There are really only two possible scenarios here:
Your modules are fully independent and there are no relationships in the database between objects belonging to different modules: use a separate schema history table per module.
Your modules do have database objects with relationships to objects belonging to other modules: you now have in effect a single global lifecycle for the database and should therefore use a single schema history table for all modules.
More info about modular applications: https://speakerdeck.com/axelfontaine/majestic-modular-monoliths
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With