Case is like this. I have liquibase changelog contaning only inserts. I am trying to force Spring Boot to initialize database (hsqldb) schema using JPA based on @Entities and later execute liquibase changelog. Unfortunatelly Spring Boot is doing it in oposite order.
I checked LiquibaseAutoConfiguration and it has:
@AutoConfigureAfter({ DataSourceAutoConfiguration.class,
HibernateJpaAutoConfiguration.class })
so it is executed after HibernateJpaAutoConfiguration however Spring Boot still do it not the way I wish ;).
Spring Boot version: 1.3.0.RELEASE Liquibase-core version: 3.5.1
Thank you in advance for any naswer
Possible solution is to disable automatic boot liquibase run via application.properties:
spring.jpa.hibernate.ddl-auto=create
liquibase.enabled=false
and then manually configure SpringLiquibase bean to depends on entityManagerFactory:
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.boot.autoconfigure.liquibase.LiquibaseProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.DependsOn;
import liquibase.integration.spring.SpringLiquibase;
@SpringBootApplication
public class DemoApplication {
@Autowired
private DataSource dataSource;
@Bean
public LiquibaseProperties liquibaseProperties() {
return new LiquibaseProperties();
}
@Bean
@DependsOn(value = "entityManagerFactory")
public SpringLiquibase liquibase() {
LiquibaseProperties liquibaseProperties = liquibaseProperties();
SpringLiquibase liquibase = new SpringLiquibase();
liquibase.setChangeLog(liquibaseProperties.getChangeLog());
liquibase.setContexts(liquibaseProperties.getContexts());
liquibase.setDataSource(getDataSource(liquibaseProperties));
liquibase.setDefaultSchema(liquibaseProperties.getDefaultSchema());
liquibase.setDropFirst(liquibaseProperties.isDropFirst());
liquibase.setShouldRun(true);
liquibase.setLabels(liquibaseProperties.getLabels());
liquibase.setChangeLogParameters(liquibaseProperties.getParameters());
return liquibase;
}
private DataSource getDataSource(LiquibaseProperties liquibaseProperties) {
if (liquibaseProperties.getUrl() == null) {
return this.dataSource;
}
return DataSourceBuilder.create().url(liquibaseProperties.getUrl())
.username(liquibaseProperties.getUser())
.password(liquibaseProperties.getPassword()).build();
}
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
However I'd strongly encourage to use liquibase to build schema as well. I believe it was designed (see org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration.LiquibaseJpaDependencyConfiguration) to run before hibernate's ddl-auto so that it's possible to set ddl-auto=validate and have liquibase schema validated by hibernate.
The solution provided by Radek Postołowicz served me quite some time but didn't work anymore after updating to spring-boot 2.5.0. I think it can be fully replaced by adding the following property to application.properties (or yml):
spring.jpa.defer-datasource-initialization=true
This is also mentioned in the release notes.
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