This guide walks through the tutorial_order_sync migration included in the test suite and shows how EvoSchema executes a real multi-datasource migration across customer and finance.
- how to define a migration component with
@DBPREDDL,@DBDML,@DBScript,@DBDMLAssert, and@DBPOSTDDL - how EvoSchema coordinates schema and data changes across multiple datasources
- how to run a migration component by name
- how to verify the final state after execution
- migration component:
TutorialOrderSyncDemo.java - integration test:
TutorialOrderSyncDemoTest.java - initial customer schema:
tutorial-order-sync-customer-schema.sql - initial finance schema:
tutorial-order-sync-finance-schema.sql - test datasource config:
unittest/db.properties
The demo simulates a release where:
- the
customerdatasource owns the order state - the
financedatasource owns the downstream sync status - the migration marks pending customer orders as
READY - the migration syncs matching finance orders to
SYNCED - the migration records an audit trail in
order_sync_log
The demo test expects two MySQL databases:
customer_dbfinance_db
The default unittest configuration is:
evoschema.datasource.customer.url=jdbc:mysql://127.0.0.1:3306/customer_db?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
evoschema.datasource.customer.username=root
evoschema.datasource.customer.password=123456
evoschema.datasource.finance.url=jdbc:mysql://127.0.0.1:3306/finance_db?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
evoschema.datasource.finance.username=root
evoschema.datasource.finance.password=123456Create both databases before running the demo:
CREATE DATABASE IF NOT EXISTS customer_db;
CREATE DATABASE IF NOT EXISTS finance_db;Before the migration runs, the test initializes the schemas from SQL files:
customer_ordersstarts with twoNEWorders and oneDONEorderfinance_ordersstarts with matching rows inPENDINGstatusorder_sync_logdoes not exist yetfinance_orders.sync_notedoes not exist yet
The demo component tutorial_order_sync executes the following phases:
@DBPREDDL(order = 1, dataSource = "customer")
public List<String> prepareTutorialTable()
@DBPREDDL(order = 2, dataSource = "finance")
public List<String> prepareFinanceColumn()These methods:
- create the
order_sync_logtable oncustomer - add the
sync_notecolumn onfinance - provide compensation SQL for rollback if a later phase fails
@DBDML(order = 1, dataSource = "customer")
public List<String> markOrdersReady()This phase updates customer orders from NEW to READY.
@DBScript(order = 2)
public void syncFinanceOrders(...)This phase:
- queries all
READYorder ids fromcustomer - updates matching
finance_ordersrows toSYNCED - inserts sync records into
order_sync_log
@DBDMLAssert(order = 3)
public void assertMigrationResult(...)This phase validates that:
- the number of
READYorders matches the number ofSYNCEDfinance rows - the sync log contains the same number of records
@DBPOSTDDL(order = 1, dataSource = "finance")
public List<String> cleanupFinanceColumn()This phase finalizes the sync_note column by setting its default value to DONE.
Compile the project:
mvn -q -DskipTests compileRun the migration by component name:
mvn -q exec:java -Dexec.args="tutorial_order_sync"You can also invoke the starter directly:
Starter.main(new String[] { "tutorial_order_sync" });After a successful run, the integration test expects:
customer_ordershas2rows with statusREADYorder_sync_loghas2rows with statusSYNCEDfinance_ordershas2rows with statusSYNCEDfinance_orders.sync_noteexists and its default value isDONE
The assertions are implemented in TutorialOrderSyncDemoTest.java.
If you want to validate the entire flow automatically:
mvn -q -Dtest=TutorialOrderSyncDemoTest testTutorialOrderSyncDemo is a compact example of EvoSchema's core value:
- code-reviewed migration logic instead of ad-hoc SQL execution
- explicit phase ordering for safer release rollouts
- multi-datasource coordination with transactional DML handling
- developer-defined rollback for Pre-DDL changes
- assertion-driven release verification before final cleanup