如何让SpringBoot主项目执行外部Liquibase库与自身的迁移脚本?
解决方案
方案一:注册多个Liquibase Bean(独立执行两个变更日志)
这种方式会创建两个Liquibase实例,分别处理库和主项目的变更日志,自动继承主项目的所有Liquibase配置(数据源、上下文、参数等)。
将公共库改造为Spring Boot Starter
在库的src/main/resources/META-INF/spring/目录下创建org.springframework.boot.autoconfigure.AutoConfiguration.imports文件,添加自动配置类的全限定名:com.your.library.config.LibraryLiquibaseAutoConfiguration编写自动配置类
创建LibraryLiquibaseAutoConfiguration类,注册两个SpringLiquibase Bean:import liquibase.integration.spring.SpringLiquibase; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.liquibase.LiquibaseProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import javax.sql.DataSource; @Configuration @ConditionalOnClass(SpringLiquibase.class) @EnableConfigurationProperties(LiquibaseProperties.class) public class LibraryLiquibaseAutoConfiguration { private final LiquibaseProperties properties; public LibraryLiquibaseAutoConfiguration(LiquibaseProperties properties) { this.properties = properties; } // 执行库的变更日志 @Bean public SpringLiquibase libraryLiquibase(DataSource dataSource) { SpringLiquibase liquibase = new SpringLiquibase(); liquibase.setDataSource(dataSource); liquibase.setChangeLog("classpath:library.xml"); // 复用主项目的Liquibase配置 liquibase.setContexts(properties.getContexts()); liquibase.setDefaultSchema(properties.getDefaultSchema()); liquibase.setDropFirst(properties.isDropFirst()); liquibase.setShouldRun(properties.isEnabled()); liquibase.setLabels(properties.getLabels()); liquibase.setChangeLogParameters(properties.getParameters()); return liquibase; } // 执行主项目的变更日志 @Bean public SpringLiquibase mainLiquibase(DataSource dataSource) { SpringLiquibase liquibase = new SpringLiquibase(); liquibase.setDataSource(dataSource); liquibase.setChangeLog(properties.getChangeLog()); // 复用主项目的Liquibase配置 liquibase.setContexts(properties.getContexts()); liquibase.setDefaultSchema(properties.getDefaultSchema()); liquibase.setDropFirst(properties.isDropFirst()); liquibase.setShouldRun(properties.isEnabled()); liquibase.setLabels(properties.getLabels()); liquibase.setChangeLogParameters(properties.getParameters()); return liquibase; } }
方案二:使用组合变更日志(单Liquibase实例执行两个文件)
这种方式通过一个组合的变更日志文件,先引入库的变更日志,再引入主项目的变更日志,只需一个Liquibase实例,执行顺序更可控。
创建组合变更日志文件
在库的src/main/resources下创建combined-changelog.xml:<?xml version="1.0" encoding="UTF-8"?> <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-4.9.xsd"> <!-- 优先执行库的变更日志 --> <include file="library.xml" relativeToChangelogFile="true"/> <!-- 再执行主项目配置的变更日志 --> <include file="${spring.liquibase.change-log}" relativeToChangelogFile="false"/> </databaseChangeLog>编写自动配置类覆盖变更日志配置
创建自动配置类,将主项目的变更日志路径作为参数传入,替换默认的change-log为组合文件:import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.liquibase.LiquibaseProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Configuration; import org.springframework.core.env.Environment; import javax.annotation.PostConstruct; @Configuration @ConditionalOnClass(name = "liquibase.integration.spring.SpringLiquibase") @EnableConfigurationProperties(LiquibaseProperties.class) public class LibraryLiquibaseAutoConfiguration { private final LiquibaseProperties liquibaseProperties; private final Environment environment; public LibraryLiquibaseAutoConfiguration(LiquibaseProperties liquibaseProperties, Environment environment) { this.liquibaseProperties = liquibaseProperties; this.environment = environment; } @PostConstruct public void setupCombinedChangeLog() { // 获取主项目原本配置的变更日志路径,默认值适配主项目的main.xml String originalChangeLog = environment.getProperty("spring.liquibase.change-log", "main.xml"); // 设置组合变更日志为默认执行文件 liquibaseProperties.setChangeLog("classpath:combined-changelog.xml"); // 将主项目的变更日志路径传入作为参数 liquibaseProperties.getParameters().put("spring.liquibase.change-log", originalChangeLog); } }配置Starter自动扫描
同样在org.springframework.boot.autoconfigure.AutoConfiguration.imports文件中添加上述配置类的全限定名,确保主项目引入后自动加载。
注意事项
- 两种方案都要求公共库是Spring Boot Starter,否则主项目无法自动加载库中的配置类。
- 方案二中,如果主项目的变更日志不是classpath下的文件,需要确保
include标签能正确定位(比如使用绝对路径或合适的资源前缀)。 - 执行顺序:方案一的两个Liquibase Bean执行顺序由Spring的Bean加载顺序决定;方案二则严格按照组合日志中的
include顺序执行(先库后主项目)。
内容的提问来源于stack exchange,提问作者Mihai Catalin Valentin
相关产品推荐
相关产品推荐

