简体   繁体   English

在spring启动应用程序中使用默认和自定义liquibase配置

[英]Use default and custom liquibase configurations in spring boot application

I'd like to use two configurations of Liquibase in current project. 我想在当前项目中使用两种Liquibase配置。 The default configuration I'd like to use for DDL changes and second one for custom inserts where changelog will be in another location. 我想用于DDL更改的默认配置,第二个用于自定义插入,其中changelog将位于另一个位置。

If I configure SpringLiquibase the default autoconfiguration will be skipped due to @ConditionalOnClass(SpringLiquibase.class) annotation in LiquibaseAutoConfiguration class. 如果我配置SpringLiquibase ,由于LiquibaseAutoConfiguration类中的@ConditionalOnClass(SpringLiquibase.class)注释,将跳过默认的自动配置。 How can I use default autoconfiguration + my custom? 如何使用默认自动配置+我的自定义? Can I overwrite the @ConditionalOnClass annotation somehow? 我可以以某种方式覆盖@ConditionalOnClass注释吗? Or maybe is there way how to tell Liquibase that I have another changelog outside of application and run it only if it's present? 或者可能有办法告诉Liquibase我在应用程序之外还有另一个更改日志,并且仅在它存在的情况下运行它?

Thanks 谢谢

edit: 编辑:

This could be the solution for my problem, however I have problem with loading external files (files outside of classpath) in liquibase. 这可能是我的问题的解决方案,但是我在liquibase中加载外部文件(类路径之外的文件)时遇到问题。

@Configuration
@EnableConfigurationProperties(LiquibaseProperties.class)
public class LiquibaseConfiguration {

    @Bean
    SpringLiquibase liquibase(DataSource dataSource, LiquibaseProperties properties) {
        SpringLiquibase liquibase = new SpringLiquibase();
        liquibase.setChangeLog(properties.getChangeLog());
        liquibase.setContexts(properties.getContexts());
        liquibase.setDataSource(dataSource);
        liquibase.setDefaultSchema(properties.getDefaultSchema());
        liquibase.setDropFirst(properties.isDropFirst());
        liquibase.setShouldRun(properties.isEnabled());
        liquibase.setLabels(properties.getLabels());
        liquibase.setChangeLogParameters(properties.getParameters());
        liquibase.setRollbackFile(properties.getRollbackFile());
        return liquibase;
    }

    @Bean
    SpringLiquibase commandInitializerLiquibase(DataSource dataSource,
            @Value("${docu.system.initializer.command.liquibase.changeLog}") String changeLogPath,
            @Value("${docu.system.initializer.command.liquibase.contexts}") String contexts) {
        File changeLog = new File(changeLogPath);
        SpringLiquibase liquibase = new SpringLiquibase();
        liquibase.setDataSource(dataSource);
        liquibase.setContexts(contexts);
        liquibase.setIgnoreClasspathPrefix(true);
        liquibase.setChangeLog(changeLog.getAbsolutePath());
        liquibase.setShouldRun(changeLog.exists());
        //liquibase.setResourceLoader(liquibaseResourceLoader());
        addPathToClassloader(changeLogPath);
        return liquibase;
    }
}

If you want to use Spring Boot autoconfigured Liquibase feature then you can have only one SpringLiquibase bean in your context. 如果您想使用Spring Boot自动配置的Liquibase功能,那么您的上下文中只能有一个SpringLiquibase bean。 This is because of @ConditionalOnMissingBean(SpringLiquibase.class) annotation in LiquibaseAutoConfiguration class. 这是因为LiquibaseAutoConfiguration类中的@ConditionalOnMissingBean(SpringLiquibase.class)注释。 Spring's conditional feature searches for SpringLiquibase instances and it's subclasses instances, so extending SpringLiquibase class won't fix that problem. Spring的条件特性搜索SpringLiquibase实例及其子类实例,因此扩展SpringLiquibase类不会解决该问题。

There is no good way to override LiquibaseAutoConfiguration . 没有好办法覆盖LiquibaseAutoConfiguration In that case you have 3 solutions which could solve your problem: 在这种情况下,您有3个解决方案可以解决您的问题:

1) Implement two separate Liquibase bean configurations: 1)实现两个单独的Liquibase bean配置:

@Configuration
public class LiquibaseConfiguration {

    @Autowired
    private DataSource dataSource;

    //define this property in your embedded properties file or use spring's default
    @Value("${liquibase.change-log}")
    private String defaultLiquibaseChangelog;

    @Bean
    public SpringLiquibase liquibase() {
        SpringLiquibase liquibase = new SpringLiquibase();
        liquibase.setDataSource(dataSource);
        liquibase.setChangeLog(defaultLiquibaseChangelog);
        // Configure rest of liquibase here...
        // ...
        return liquibase;
    }
}

and

@Configuration
public class LiquibaseConfiguration2 {

    @Autowired
    private DataSource dataSource;

    //optional, define it in external configuration or through command line param
    @Value("${liquibase.change-log-additional:#{null}}")
    private String additionalLiquibaseChangelog;

    @Bean(name = "additionalLiquibase")
    public SpringLiquibase liquibase() {
        if (additionalLiquibaseChangelog != null) {
            SpringLiquibase liquibase = new SpringLiquibase();
            liquibase.setDataSource(dataSource);
            liquibase.setChangeLog(additionalLiquibaseChangelog);
            // Configure rest of liquibase here...
            // ...
            return liquibase;
        }
        return null;
    }
}

2) Use Liquibase instead of SpringLiquibase for manually configured liquibase instance 2)使用Liquibase而不是SpringLiquibase来手动配置liquibase实例

Use one autoconfigured SpringLiquibase and one pure Liquibase configuration instead of SpringLiquibase (You will need to manually run your migrations and handle other stuff which is implemented in SpringLiquibase ) 使用一个自动配置的SpringLiquibase和一个纯Liquibase配置而不是SpringLiquibase (您需要手动运行迁移并处理SpringLiquibase实现的其他内容)

3) Use only one SpringLiquibase instance 3)仅使用一个SpringLiquibase实例

Use combination of Liquibase's changelogParameters ( http://www.liquibase.org/documentation/changelog_parameters.html ), include tag ( http://www.liquibase.org/documentation/include.html ) and only one SpringLiquibase instance. 使用Liquibase的changelogParametershttp://www.liquibase.org/documentation/changelog_parameters.html ), include标签( http://www.liquibase.org/documentation/include.html )和一个SpringLiquibase实例的组合。

Example implementation: 示例实现:

Liquibase bean configuration Liquibase bean配置

@Configuration
public class LiquibaseConfiguration {

    @Autowired
    private DataSource dataSource;

    //define this property in your embedded properties file or use spring's default
    @Value("${liquibase.change-log}")
    private String defaultLiquibaseChangelog;

    //define this property in your embedded properties file
    @Value("${liquibase.extended-change-log}")
    private String extendedLiquibaseChangelog;

    //optional, define it in external configuration or through command line param
    @Value("${liquibase.data-change-log:#{null}}")
    private String liquibaseDataChangelog;

    @Bean
    public SpringLiquibase liquibase() {
        SpringLiquibase liquibase = new SpringLiquibase();
        liquibase.setDataSource(dataSource);
        if (liquibaseDataChangelog != null) {
            //here you can check if file exists...
            Map<String, String> liquibaseChangelogParameters = new HashMap<>();
            liquibaseChangelogParameters.put("liquibaseExternalDataChangelogPath", liquibaseDataChangelog);
            liquibase.setChangeLog(extendedLiquibaseChangelog);
            liquibase.setChangeLogParameters(liquibaseChangelogParameters);
        } else {
            liquibase.setChangeLog(defaultLiquibaseChangelog);
        }
        // Configure rest of liquibase here...
        // ...
        return liquibase;
    }
}

changelog.xml (liquibase.change-log) changelog.xml(liquibase.change-log)

<databaseChangeLog
        xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.3.xsd">

    <include relativeToChangelogFile="true" file="changelog-master.xml"/>

</databaseChangeLog>

changelog-with-external-data.xml ( liquibase.extended-change-log ) changelog-with-external-data.xml(liquibase.extended-change-log)

<databaseChangeLog
        xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.3.xsd">

    <include relativeToChangelogFile="true" file="changelog-master.xml"/>
    <include relativeToChangelogFile="false" file="${liquibaseDataChangelogPath}"/>

</databaseChangeLog>

Remember that having separate changelogs could be dangerous. 请记住,单独更改日志可能很危险。 You have to make sure that your changelogs are independent: 您必须确保您的更改日志是独立的:

Included change-logs are run in the order they are found so care does need to be taken to make sure that the included changelogs are either completely independent, or that any required changelogs are run first. 包含的更改日志按找到的顺序运行,因此需要注意确保包含的更改日志完全独立,或者首先运行所需的更改日志。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM