春季启动。在hsqldb上生成jpa auto-dll表之后运行liquibase changelog

时间:2016-07-07 08:01:41

标签: jpa spring-boot liquibase

案例是这样的。 我有liquibase changelog仅包含插入。 我试图强制Spring Boot使用基于@Entities的JPA初始化数据库(hsqldb)模式,然后执行liquibase changelog。不幸的是,Spring Boot正在按照相反的顺序进行。

我检查了LiquibaseAutoConfiguration,它有:

@AutoConfigureAfter({ DataSourceAutoConfiguration.class,
        HibernateJpaAutoConfiguration.class })

所以它是在HibernateJpaAutoConfiguration之后执行的,但Spring Boot仍然按照我希望的方式执行;)。

Spring Boot版本:1.3.0.RELEASE Liquibase-core版本:3.5.1

提前感谢您提供任何理由

3 个答案:

答案 0 :(得分:5)

可能的解决方案是禁用通过application.properties

运行的自动启动liquibase
spring.jpa.hibernate.ddl-auto=create
liquibase.enabled=false

然后手动配置SpringLiquibase bean取决于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);
    }
}

但是,我强烈建议您使用liquibase来构建架构。我相信它是在hibernate org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration.LiquibaseJpaDependencyConfiguration之前设计的(请参阅ddl-auto),以便可以设置ddl-auto=validate并通过hibernate验证liquibase模式。< / p>

答案 1 :(得分:0)

Radek Postołowicz 提供的解决方案为我服务了很长时间,但在更新到 spring-boot 2.5.0 后不再起作用。我认为可以通过将以下属性添加到 1- User scans QR code. 2- Click on the link produced from the QR code scanner. 3- Safari mobile browser opens and stores in local storage user credentials encoded Base64. 4- User is redirected to the App store to download our application. 5- Application is downloaded then user clicks on open. 6- When the application opens it checks if the (in-app) safari browser has local storage or not if yes we use this encoded data. (或 yml)来完全替换它:

application.properties

release notes 中也提到了这一点。

答案 2 :(得分:0)

我刚刚将 Spring Boot 更新到 2.5.3 并且遇到了同样的问题。 我通过使用类 CustomSpringLiquibase(Kotlin 版本)解决了这个问题:

class CustomSpringLiquibase(
        private var springLiquibase: SpringLiquibase
) : InitializingBean, BeanNameAware, ResourceLoaderAware {

    companion object {
        private val LOGGER = LoggerFactory.getLogger(CustomSpringLiquibase::class.java)
    }

    @Throws(LiquibaseException::class)
    override fun afterPropertiesSet() {
        LOGGER.info("Init Liquibase")
        springLiquibase.afterPropertiesSet()
    }

    override fun setBeanName(name: String) {
        springLiquibase.beanName = name
    }

    override fun setResourceLoader(resourceLoader: ResourceLoader) {
        springLiquibase.resourceLoader = resourceLoader
    }
}

在我的 SpringBootApplication 类中,我添加了以下内容(Java 版本):

@Bean
@DependsOn(value = "entityManagerFactory")
public CustomSpringLiquibase liquibase() {
    LiquibaseProperties liquibaseProperties = liquibaseProperties();
    SpringLiquibase liquibase = new SpringLiquibase();
    ....
    return new CustomSpringLiquibase(liquibase);
}