【问题标题】:Liquibase's DbDoc listing all changes as "Pending / Not yet ran"Liquibase 的 DbDoc 将所有更改列为“待处理/尚未运行”
【发布时间】:2015-04-29 13:08:35
【问题描述】:

Liquibase 已集成到我们的 Spring 应用程序中,并且在应用程序启动阶段执行数据库迁移。

通过 Maven 插件运行 DbDoc 时,所有更改都报告为“Pending Changes (NOT YET RAN)”。所以我无法为我们的下一个版本创建差异视图。

我发现的问题是 Spring bean 对 DATABASECHANGELOG 表中的更改日志条目使用类路径相对路径。通过 Maven 插件运行 DbDoc 时,使用相对于 Maven 项目根目录的文件路径。

NotRanChangeSetFilter 的代码无法处理这种差异: http://grepcode.com/file/repo1.maven.org/maven2/org.liquibase/liquibase-core/3.3.2/liquibase/changelog/filter/NotRanChangeSetFilter.java

尤其是下面的比较是行不通的:

ranChangeSet.getChangeLog().equalsIgnoreCase(changeSet.getFilePath())

这些方法返回以下值:

getChangeLog(): classpath:changelog/5.3.3/nos_add_acp_data.xml
getFilePath(): src/main/resources/changelog/5.3.3/nos_add_acp_data.xml

因此,equalsIgnoreCase 比较失败,这导致所有更改都被列为“Pending / NOT YET RAN”。

是否有任何已知的解决方法?我能想到的唯一解决方案是提供我们自己的 NotRanChangeSetFilter 实现,并在执行 Liquibase Maven 插件之前将其放在类路径中。是否有任何其他想法甚至官方解决此问题?

2015-04-30 更新: 经过大量调试,我认为 DATABASECHANGELOG 表中的路径必须在存储之前进行规范化。此外,每个工具还必须标准化其路径,以便比较工作。我在代码中发现了以下与当前概念比较失败的地方:

  • RanChangeSetFilter.getRanChangeSet():equalsIgnoreCase() 比较
  • ValidatingVisitor.visit():ranIndex.get(changeSet.toString(false));
  • NotRanChangeSetFilter.accepts():equalsIgnoreCase() 比较
  • RanChangeSet.isSame():equalsIgnoreCase() 比较

在后者中,有一个“normalize()”方法从路径中去除 classpath: 前缀。但这只是 4 个地方之一。

DbDoc 工具似乎能够使用相对于 Maven 项目根目录的源代码路径和类路径路径。所以在一个MAven项目中有如下配置选项:

<changeLogFile>changelog/complete.xml</changeLogFile> -> "classpath:" prefix is missing in the comparison

<changeLogFile>src/main/resources/changelog/complete.xml</changeLogFile> -> "src/main/resources" is the prefix in the comparisons

顺便说一句,第一个选项应该记录在 Maven 插件文档中。

拉取请求以使 DbDoc Maven 插件工作: https://github.com/liquibase/liquibase/pull/413

问候, 迈克尔

【问题讨论】:

    标签: liquibase


    【解决方案1】:

    你是对的,差异是由于 Liquibase 存储的文件路径的差异。每个 changeSet 都由 id+author+filepath 的组合标识,因此您需要确保文件路径在所有运行 Liquibase 的方式中保持一致。

    通常最好的方法是将变更日志文件放在类路径中,并始终使用相对于类路径的路径引用变更日志,例如“changelog/5.3.3/nos_add_acp_data.xml”。

    我不确定您目前是如何引用文件的。如果您使用的是 3.3.2,那么您可能会遇到一个与 includeAll 如何与 spring 一起工作的问题,该问题已在 3.3.3 中得到解决。

    否则,您始终可以使用根 databaseChangeLog 节点上的“logicalFilePath”属性对 liquibase 用作路径的内容进行硬编码,以便您始终知道它是相同的,但它被引用了。

    【讨论】:

    • 对我来说,路径的概念似乎有点被打破了。应该从 DATABASECHANGELOG 表中删除“classpath:”前缀,并且查看该表以查找已经执行的变更日志的工具需要确保路径是规范化的。如果我为 DbDoc Maven 插件指定 changelog/complete.xml,则似乎通过类路径找到了 complete.xml,但在查看表时缺少前缀“类路径:”,所以所有比较失败。
    • 包含它的想法,这样您就不必担心所有文件中的唯一 ID,只需在一个文件中。 Spring 添加了 classpath: 前缀,这确实会导致问题,但 LIquibase 应该在比较逻辑中处理它。
    • 我建议创建一个实用程序类进行比较并在那里添加各种规范化:“类路径:”前缀删除,“src/main/resources”前缀删除,斜杠/反斜杠转换,...然后你可以在所有需要比较的地方使用这个比较器。
    • 谢谢,我会看看拉取请求。集中逻辑也是一个好主意。
    猜你喜欢
    • 2011-03-07
    • 2013-01-19
    • 2019-05-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-10
    • 2020-10-17
    • 2011-02-15
    相关资源
    最近更新 更多