升级Liquibase版本后类路径部分文件无法找到的问题排查
Liquibase 4.24.0 全新数据库初始化时无法读取Fat Jar中的子变更日志文件
问题现象
- 用Testcontainer搭建备份数据库,通过Shell调用Liquibase CLI执行
update做初始化,主变更日志能在Fat Jar中找到,但它引用的子变更文件(写法为<include file="dbs/X/v1.0/X.xml"/>)被Liquibase强制在本地目录查找,报错日志:[2023-11-02 21:02:56] FINE [liquibase.resource] Path dbs/X/X/increments/X.xml in
does not exist (liquibase.resource.DirectoryResourceAccessor ( )) - 这些子文件实际存在于Fat Jar内部
- 版本相关触发条件:
- 回退到Liquibase 4.9.1可正常运行
- 已有数据的数据库用4.24.0执行
update无异常,仅全新数据库初始化时触发问题
- 当前临时 workaround:放弃新版本的labels功能,改用contexts过滤变更集
问题原因
Liquibase 4.24.0在全新数据库初始化流程中修改了资源访问逻辑:当数据库中不存在Liquibase元数据表(如databasechangelog)时,会优先使用DirectoryResourceAccessor读取本地目录,而非从主变更日志所在的类路径(Fat Jar)加载子文件。旧版本(如4.9.1)则会始终从主变更日志的资源路径解析引用的子文件。
解决办法
1. 显式指定类路径资源访问器
执行Liquibase命令时,强制指定使用ClasspathResourceAccessor,让Liquibase从类路径加载所有变更文件:
liquibase --changeLogFile=classpath:/your/main/changelog.xml --resource-accessor=liquibase.resource.ClasspathResourceAccessor update
将/your/main/changelog.xml替换为Fat Jar中主变更日志的实际类路径。
2. 修改子变更日志的引用路径
把<include>标签内的路径改为类路径绝对格式,明确告知Liquibase从类路径加载:
<include file="classpath:/dbs/X/v1.0/X.xml"/>
这种方式无需修改CLI命令,直接调整变更日志文件即可。
3. 先初始化元数据表再执行更新
利用"已有元数据表时4.24.0可正常工作"的特性,先手动同步变更日志初始化元数据表,再执行更新:
- 先执行:
liquibase changelog-sync - 再执行:
liquibase update
以此绕过全新数据库时的资源访问逻辑问题。
验证要点
- 测试时确保Testcontainer启动的是完全干净的数据库(无Liquibase元数据表)
- 确认Fat Jar已正确打包所有变更日志文件,类路径配置无误
内容的提问来源于stack exchange,提问作者Martin Mucha
相关产品推荐
相关产品推荐

