【问题标题】:Liquibase rollback from command line not working从命令行回滚 Liquibase 不起作用
【发布时间】:2019-08-13 22:10:17
【问题描述】:

我正在 Windows 环境中执行一个 tomcat 应用程序,该应用程序在部署时会在 oracle 数据库上创建/更新数据库架构。为此,我使用的是 Liquibase SDK 3.3.2。所以基本上我调用 SDK 并告诉它从我的 changelog.xml 中进行更新。这部分工作正常。 java类的代码

...
Liquibase liquibase = new Liquibase(CHANGE_LOG,
                new ClassLoaderResourceAccessor(getClass().getClassLoader()), db);

liquibase.update("");

问题是,当出现问题并且我从命令行执行回滚时,什么也没有发生。我没有收到任何异常或错误消息。只是一条消息“回滚成功”,但在数据库中根本没有任何变化。现在有趣的是,当我从 cmd 更新我的更改日志文件,然后也从 cmd 进行回滚时,回滚就可以工作了。命令行调用如下所示:

Liquibase --changeLogFile=C:\myProject\src\main\resources\database\master.xml  --logLevel=DEBUG rollbackCount 5

我的 liquibase.properties 文件如下所示:

driver: oracle.jdbc.OracleDriver 
classpath:ojdbc6.jar 
url: jdbc:oracle:thin:@192.168.56.101:1521:orcl
username: myUser
password: mypassword

有人知道为什么会这样吗? SDK和cmd工具有什么不兼容的地方吗?

【问题讨论】:

  • 使用“rollbackCountSQL”命令查看将应用的 SQL。
  • 您好已经试过了。从 SDK 更新和从命令行回滚没有 SLQ 的相同效果。从命令行更新和从命令行回滚我得到了正确的 SQL

标签: java liquibase


【解决方案1】:

问题在于更改日志文件的路径。 Liquibase 将 chengeLog 的路径存储在某处,并在调用时将其与给定的更改日志进行比较。如果它们不是同一个,Liquibase 将继续运行,而不会出现 changeLog 和警告。

所以在我的情况下,当从 tomcat 应用程序调用 Liquibase 时,路径是:database\master.xml,当从控制台调用它时,我给出了路径 C:\myProject\src \main\resources\database\master.xml 在命令行中。这导致该方法返回 null,尽管 Liquibase 知道 changeLog 的路径。所以这就是它不起作用的原因。

解决方法 是从命令行从与应用程序使用相对路径相同的文件夹调用 liquibase。

技术原因: 在调试 LB 之后,我发现了这个。 DatabaseChageLog.getChangeSet() 方法返回 null,尽管 chanegeLog 路径是正确的。这发生在创建 ChangeLogIterator 以在方法 Liquibase.rollback(int changesToRollback, Contexts contexts, LabelExpression labelExpression) 中运行 RollbackVisitorValidationVisitor 不会发生这种情况,因为 ChangeLogIterator 的创建方式不同,这就是为什么我没有收到任何错误\警告

【讨论】:

  • 不确定它是否将更改日志路径存储在数据库或其他任何地方,但在指定迁移文件的相对路径(./)时肯定会出现误报。我必须站在保存文件的目录中并执行 --changeLogFile=migrations.xml 而不是 --changeLogFile=./migrations.xml 才能使其工作。
【解决方案2】:

为了其他读者的利益,我想补充一下我的经验和理解。

了解从命令行运行回滚时发生的情况很重要

  • Liquibase 查阅您通过 --changeLogFile 参数提供的变更日志文件。

  • 它将遍历此文件中提到的变更集,将它们的校验和与DATABASECHANGELOG 数据库表中相应记录的校验和进行比较。

  • 现在重要的一点是:校验和是根据文件名(包括路径)和文件内容计算得出的。

  • 如果校验和不匹配,则变更集不符合回滚条件。

  • 如果您从 Web 应用程序内部运行 Liquibase,则 Liquibase 更改日志可能位于类路径中,这意味着 DATABASECHANGELOG 表中的文件名列以类路径为前缀:

ID 作者 文件名 CreateWidgetTable NabilH 类路径:liquibase/sprint1/create.widget.table.xml
  • 通过命令行运行时不是这种情况

  • 这将导致校验和验证失败并忽略变更集

但是,我认为有比您提出的更好的解决方案。您可以将 Liquibase 命令行的 --classpath 参数指向您的 WAR,并指定相对于类路径的 --changeLogFilePath

假设我将更改日志存储在 src/main/resources/liquibase/changelog.xml 中。

因此,在类路径上,此文件可通过 liquibase/changelog.xml 访问。

java -jar lib/liquibase-core-3.5.3.jar\
    --url=jdbc:h2:tcp://localhost/~/test --username=sa --password=\
    --logLevel=DEBUG --classpath=/opt/tomcat9/webapps/springLiquibase.war\
    --changeLogFile=liquibase/changelog.xml rollback v1

【讨论】:

  • 很好的总结,这涵盖了端到端!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-02-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-25
  • 2021-07-29
  • 2018-05-10
相关资源
最近更新 更多