自定义Spring Boot Starter中Liquibase迁移未加载的配置求助
自定义Spring Boot Starter中Liquibase脚本加载问题解决
问题背景
开发了一款可被任意项目引入的自定义Spring Boot Starter,需在主应用数据库中创建若干表,因此在Starter模块中用Liquibase编写迁移脚本,并在Starter的application.properties中配置:
spring.datasource.url=jdbc:postgresql://localhost:5432/message spring.liquibase.change-log=classpath:liquibase/changelog.xml
但主应用引入该Starter启动时,抛出异常:
Description: Liquibase failed to start because no changelog could be found at 'classpath:/db/changelog/db.changelog-master.yaml'. Action: Make sure a Liquibase changelog is present at the configured path.
主应用仅在自身项目内查找迁移路径,未加载Starter中的脚本,需解决如何让主应用自动加载Starter的Liquibase迁移,或用其他方式在表缺失时执行SQL脚本。
解决方法
方法一:Starter自动配置类自定义Liquibase Bean
Spring Boot默认的Liquibase自动配置会优先读取主应用的配置,可在Starter中编写自动配置类,手动注册Liquibase实例,指定Starter的changelog路径,同时兼容主应用配置:
@Configuration @ConditionalOnClass(Liquibase.class) @ConditionalOnProperty(prefix = "spring.liquibase", name = "enabled", matchIfMissing = true) public class StarterLiquibaseAutoConfiguration { @Bean @ConditionalOnMissingBean public Liquibase starterLiquibase(DataSource dataSource, LiquibaseProperties properties) throws SQLException { DatabaseConnection connection = new JdbcConnection(dataSource.getConnection()); Liquibase liquibase = new Liquibase("classpath:liquibase/changelog.xml", new ClassLoaderResourceAccessor(), connection); liquibase.update(properties.getContexts()); return liquibase; } }
同时在Starter的META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件中注册该自动配置类:
com.yourpackage.StarterLiquibaseAutoConfiguration
方法二:主应用合并加载多Changelog
若主应用本身也使用Liquibase,可在主应用的主changelog文件中引入Starter的脚本,实现统一加载:
比如主应用的db/changelog/db.changelog-master.yaml中添加:
databaseChangeLog: - include: file: classpath:liquibase/changelog.xml
这种方式需要主应用配合,但能统一管理所有迁移脚本的执行顺序。
替代方案:Spring Boot Schema初始化
若不需要Liquibase的版本管理功能,可直接用Spring Boot自带的Schema初始化:
- 在Starter的
resources下创建schema.sql,编写带IF NOT EXISTS的建表SQL,避免重复创建:
CREATE TABLE IF NOT EXISTS message ( id SERIAL PRIMARY KEY, content TEXT NOT NULL, create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP );
- 在Starter的自动配置类中配置数据源初始化器:
@Configuration public class StarterSchemaAutoConfiguration { @Bean public DataSourceInitializer dataSourceInitializer(DataSource dataSource) { DataSourceInitializer initializer = new DataSourceInitializer(); initializer.setDataSource(dataSource); ResourceDatabasePopulator populator = new ResourceDatabasePopulator(); populator.addScript(new ClassPathResource("schema.sql")); initializer.setDatabasePopulator(populator); initializer.setEnabled(true); return initializer; } }
内容的提问来源于stack exchange,提问作者Kirill Zhurbin
相关产品推荐
相关产品推荐

