java-在Spring Boot应用程序中使用默认和自定义liquibase配置
作者:互联网
我想在当前项目中使用Liquibase的两种配置.我想用于DDL更改的默认配置,第二个用于自定义插入的默认配置,其中changelog将位于另一个位置.
如果我配置SpringLiquibase,则由于LiquibaseAutoConfiguration类中的@ConditionalOnClass(SpringLiquibase.class)批注,将跳过默认的自动配置.
如何使用自定义的默认自动配置?我可以以某种方式覆盖@ConditionalOnClass注释吗?或者,也许有什么方法可以告诉Liquibase我在应用程序之外还有另一个changelog并仅在存在时运行它?
谢谢
编辑:
这可以解决我的问题,但是我在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;
}
}
解决方法:
如果要使用Spring Boot自动配置的Liquibase功能,则上下文中只能有一个SpringLiquibase bean.
这是因为LiquibaseAutoConfiguration类中的@ConditionalOnMissingBean(SpringLiquibase.class)批注. 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(http://www.liquibase.org/documentation/changelog_parameters.html),包含标签(http://www.liquibase.org/documentation/include.html)和仅一个SpringLiquibase实例.
示例实现:
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)
<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)
<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>
请记住,拥有单独的变更日志可能很危险.您必须确保您的变更日志是独立的:
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.
标签:spring-boot,liquibase,spring,java 来源: https://codeday.me/bug/20191026/1939023.html