Issue
I'm using Flyway to update the DB schema. Currently, the latest version of the schema is 3 (the latest migration file is named V3__postgres.sql
).
If I run the application on a database which has an older schema version, Flyway executes the update scripts as expected. However, if I run the app on a new (empty) database, flyway tries to execute the update scripts, but it doesn't find any tables (because Hibernate didn't create them yet), and the app terminates on error.
I would like Flyway to not execute the update scripts on an empty database, since when Hibernate creates the tables, they will be at the latest version anyway.
If I understand it correctly, I should be able to use parameter flyway.baseline-version
for this. My theory is that if Flyway doesn't find table schema_version
, it should create it and insert a record saying that the DB is at version 3. But even if I set flyway.baseline-version=3
, Flyway executes the scripts anyway. I also tried to set parameter flyway.baseline-on-migrate=true
and their different combinations but I couldn't get it to work.
Do I understand the baseline-version
parameter correctly or am I missing something?
Note: I'm aware that since Spring Boot 2 the parameter namespace has changed to spring.flyway.*
, but I'm using Spring Boot 1 so that is not the problem.
Solution
Solved: I created a custom FlywayMigrationStrategy
bean where I manually check if Flyway has been already introduced to the database (by checking if the migration table exists). If not, I run the baseline
command. Then I call the migrate
command as usual.
Here is the Spring Boot configuration:
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.flyway.FlywayMigrationStrategy;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FlywayConfig {
@Autowired
private DataSource dataSource;
@Value("${flyway.table}")
private String flywayTableName;
@Value("${flyway.baselineVersionAsString}")
private String baselineVersion;
@Bean
public FlywayMigrationStrategy flywayMigrationStrategy() {
return flyway -> {
if (!isFlywayInitialized()) {
flyway.setBaselineVersionAsString(baselineVersion);
flyway.baseline();
}
flyway.migrate();
};
}
private boolean isFlywayInitialized() {
try (Connection connection = dataSource.getConnection()) {
DatabaseMetaData metadata = connection.getMetaData();
ResultSet result = metadata.getTables(null, null, flywayTableName, null);
return result.next();
} catch (SQLException e) {
throw new RuntimeException("Failed to check if Flyway is initialized", e);
}
}
}
Answered By - Jardo
Answer Checked By - Mildred Charles (JavaFixing Admin)