-
Notifications
You must be signed in to change notification settings - Fork 41.2k
Restore run order of data.sql
/schema.sql
against high-level database migration tools
#26692
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
We talked about this issue today and decided that we'd like to restore the old order (if it's not too hard) so that upgrades are easier. We don't want to remove the documentation note since we still think it's best not to mix technologies but we'll try to add a how-to note describing test-only migrations (see #26796). |
data.sql
and high-level database migration tools.data.sql
/schema.sql
against high-level database migration tools
Update `DatabaseInitializationDependencyConfigurer` so that depends-on ordering is applied based on the `DatabaseInitializerDetector` order. Prior to this commit, if multiple DatabaseInitializer beans were detected the order in which they were initialized was not defined. See gh-26692
Probably this change has broken our build test pipeline, because it was working with <= 2.5.0. we use |
@gbrehmer I'm having exactly the same problem. |
Sorry for the inconvience. This only really worked in 2.4 and earlier by accident rather than design. We used to document that it wouldn't work at all, but refined that to more accurately reflect the (rather complex) reality. Since that update in Spring Boot 2.3.x, the documentation has said the following:
In short, you should move away from using both @Bean
@Order(Ordered.LOWEST_PRECEDENCE)
static BeanFactoryPostProcessor databaseInitializationReordering() {
return (beanFactory) -> {
modifyDependencies(beanFactory.getBeanDefinition("liquibase"),
(dependencies) -> dependencies.add("dataSourceScriptDatabaseInitializer"));
modifyDependencies(beanFactory.getBeanDefinition("dataSourceScriptDatabaseInitializer"),
(dependencies) -> dependencies.remove("liquibase"));
};
}
static void modifyDependencies(BeanDefinition definition, Consumer<Set<String>> modifier) {
String[] dependsOn = definition.getDependsOn();
Set<String> dependencies = new LinkedHashSet<>(
dependsOn != null ? Arrays.asList(dependsOn) : Collections.emptySet());
modifier.accept(dependencies);
definition.setDependsOn(dependencies.toArray(new String[0]));
} This'll make it possible to restore 2.4.x's ordering with 2.5 but it should only be relied upon in the short-term and, as I said above, you should move to using a single database initialization tool as soon as you can. |
Ok so we need a new solution to reduce test duration. and that will probably be a difficult task |
Perhaps you can write a JUnit test extension that could prepare your database before the Spring ApplicationContext is initialized. The actual code used to run the script is pretty minimal. You might even be able to use the |
@philwebb thanks for the hints. you can add init script to h2 connection string: Because init command is called for every connection, it should only be added to the liquibase url |
Spring Boot 2.5 changed the order in which high-level database migration tools like Flyway and Liquibase and the Spring specific
data.sql
andschema.sql
are run.Prior to 2.5 one was able to define a schema via Flyway and add an additional
data.sql
to populate the scheme. While this is not that useful in production, it is very valuable during tests.For example, here's a schema from Flyway: https://github.com/michael-simons/biking2/tree/3d753e6c1dee236c81170ce4933223ce1379d2e8/src/main/resources/db/migration
In the test resources is a
data.sql
https://github.com/michael-simons/biking2/blob/5694e1c85f4df0961a106f586c3911954a99ab15/src/test/resources/data.sql which will be picked up via@DataJpaTest
.This works because first Flyway (or Liquibase) runs, create the schema and then the inserts are run.
While I completely agree that having a
scheme.sql
AND a migration tool doesn't make sense or even is harmful, combining migrations and data isn't.Together with
spring.datasource.initialization-mode=never
(see this test one was able to selectively disable any additional data with one simple property.In the case of Flyway (and my small example (I do have more, I like that pattern)), I can rework this basically with that idea
using a repeatable migration, but that is brittle and will start to cause issues when there are repeatables in production already, as one has to fiddle with their ordering.
So my suggestion is to restore the old order or provide an additional property like
spring.jpa.defer-datasource-initialization
but for Flyway/Liquibase with the same result.I also hope you do reconsider this plan stated in the 2.5 docs:
Thank you.
Edit: For Flyway there is an actual solution via Callbacks: https://flywaydb.org/documentation/concepts/callbacks (Via Richard on Twitter)
Here's my (final) solution: michael-simons/biking2@3dc263d The use case described above can be solved with Flyway alone. I don't know about Liquibase enough to propose something with it.
The text was updated successfully, but these errors were encountered: