Introduce MigrationContext to be prepared for JDBC migration refactor#152
Introduce MigrationContext to be prepared for JDBC migration refactor#152rbygrave merged 2 commits intoebean-orm:masterfrom
Conversation
|
FYI: We do not use AutoRunner, as we have a multi-tenant setup. private Database database;
void initDatabase() { // will be invoked for each tenant (in multiple threads)
// every JDBC migration inherits from AbstractJdbcMigration class and stores current DB in a threadLocal
AbstractJdbcMigration.setDb(database);
try {
MigrationConfig migrationConfig = new MigrationConfig();
// ... set up config
// I want to pass my own context here, so that I can remove the threadLocal and
// have a
new MigrationRunner(migrationConfig).run(database.dataSource());
} finally {
AbstractJdbcMigration.setDb(database);
}
}Layout of the AbstractJdbcMigration: public abstract class AbstractJdbcMigration implements JdbcMigration {
private static final ThreadLocal<Database> DB = new ThreadLocal<>();
public static void setDb(final Database db) {
if (db == null) {
DB.remove();
} else {
DB.set(db);
}
}
public void migrate(final Connection connection) {
SpiEbeanServer defaultServer = (SpiEbeanServer) DB.get();
assert defaultServer != null;
TransactionManager transactionManager = (TransactionManager) defaultServer.transactionManager();
SpiTransaction txn = transactionManager.wrapExternalConnection(connection);
transactionManager.externalBeginTransaction(txn, TxScope.notSupported());
try {
migrate(defaultServer);
txn.flush();
} finally {
transactionManager.externalRemoveTransaction();
}
}
protected abstract void migrate(Database db);
}Example migration. public class V1_2_3_MigrateSomeJson extends AbstractJdbcMigration {
@Data
static class MyDto {
private UUID id;
private String someJson;
}
protected void migrate(final Database db) {
List<MyDto> lst = db.findDto(MyDto.class, "select id, some_json from my_table");
for (MyDto dto : lst) {
db.sqlUpdate("update my_table set some_json = :json where id = :id)
.setParameter("json", convertJson(dto.getSomeJson))
.setParameter("id", dto.getId())
.update()
}
}
String convertJson(String oldJson) {
// convert the JSON with Jackson ObjectMapper
}
}This migrates the JSON content of an existing field.
|
| * | ||
| * @author Roland Praml, FOCONIS AG | ||
| */ | ||
| public class DefaultMigrationContext implements MigrationContext { |
There was a problem hiding this comment.
It would be great, if ebean-migration can have a dependency to have access to "Database". What do you think about this idea?
Otherwise, I plan to imlement a EbeanMigrationContext extends DefaultMigrationContext, that has a Database getDb() method in our application and cast to this context in our JdbcMigrations
There was a problem hiding this comment.
have access to "Database".
Yes, I would expect it along with a ebean Transaction - so with Database and Transaction then Jdbc Migrations can use all the features of ebean etc.
There was a problem hiding this comment.
Note that I don't expect this DefaultMigrationContext to be public.
ebean-migration/src/main/java/io/ebean/migration/runner/MigrationEngine.java
Show resolved
Hide resolved
| * | ||
| * @author Roland Praml, FOCONIS AG | ||
| */ | ||
| public class DefaultMigrationContext implements MigrationContext { |
There was a problem hiding this comment.
have access to "Database".
Yes, I would expect it along with a ebean Transaction - so with Database and Transaction then Jdbc Migrations can use all the features of ebean etc.
| * | ||
| * @author Roland Praml, FOCONIS AG | ||
| */ | ||
| public class DefaultMigrationContext implements MigrationContext { |
There was a problem hiding this comment.
Note that I don't expect this DefaultMigrationContext to be public.
Hello @rbygrave ,
I tried to extract the planned MigrationContext from #151, so that the PR does not become too big.
It would be good, if I get feedback, so this gets merged soon. Then I'll continue with #151. (probably next year)
This PR should not introcude breaking changes.
Roland