在spring boot application

时间:2016-08-18 09:22:36

标签: java spring spring-boot liquibase

我想在当前项目中使用两种Liquibase配置。我想用于DDL更改的默认配置,第二个用于自定义插入,其中changelog将在另一个位置。

如果我配置SpringLiquibase,由于@ConditionalOnClass(SpringLiquibase.class)类中的LiquibaseAutoConfiguration注释,将跳过默认的自动配置。 如何使用默认自动配置+我的自定义?我可以以某种方式覆盖@ConditionalOnClass注释吗?或者也许有办法告诉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;
    }
}

1 个答案:

答案 0 :(得分:4)

如果您想使用Spring Boot自动配置的Liquibase功能,那么您的上下文中只能有一个SpringLiquibase bean。 这是因为@ConditionalOnMissingBean(SpringLiquibase.class)类中的LiquibaseAutoConfiguration注释。 Spring的条件特征搜索SpringLiquibase个实例及其子类实例,因此扩展SpringLiquibase类不会解决该问题。

没有好方法可以覆盖LiquibaseAutoConfiguration。 在这种情况下,您有3个解决方案可以解决您的问题:

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;
    }
}

@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)对手动配置的liquibase实例使用Liquibase代替SpringLiquibase

使用一个自动配置SpringLiquibase和一个纯Liquibase配置而不是SpringLiquibase(您需要手动运行迁移并处理SpringLiquibase中实现的其他内容)

3)仅使用一个SpringLiquibase实例

使用Liquibase的changelogParameters include),SpringLiquibase标记(http://www.liquibase.org/documentation/changelog_parameters.html)和只有一个@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; } } 实例的组合。

示例实施:

Liquibase bean配置

<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.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"/>
    <include relativeToChangelogFile="false" file="${liquibaseDataChangelogPath}"/>

</databaseChangeLog>

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

 1 #include<string.h>
 2 #include<stdio.h>
 3 #define print(x,c)      while(x>0)\
 4 {\
 5         puts(c);\
 6         printf("\n");\
 7         --x;\
 8 }
 9 
 10 int main()
 11 {
 12         char c[20];
 13         strcpy(c,"Hallelujah");
 14         print(5,c);
 15 }

请记住,单独更改日志可能会很危险。您必须确保您的更改日志是独立的:

  

包含的更改日志按照找到的顺序运行,因此需要小心   需要采取措施以确保包含的更改日志   完全独立,或者首先运行任何所需的更改日志。