Liquibase从命令行回滚不起作用

时间:2015-03-19 14:51:28

标签: java liquibase

我正在windows环境中进行tomcat appliaction,当部署时在oracle db上创建/更新DB Schema。为此我使用的是Liquibase SDK 3.3.2。所以基本上我打电话给SDK告诉它从我的changelog.xml做一个更新。这部分工作正常。 代码构成了java类

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

liquibase.update("");

问题是,当出现问题并且我从命令行执行回滚时没有任何反应。我没有得到任何例外或错误消息。只是一条消息“Rollback successcesfull”,但在DB中根本没有变化。现在有趣的是,当我从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工具之间是否存在任何不兼容性?

2 个答案:

答案 0 :(得分:3)

问题是更改日志文件的路径。 Liquibase存储了chengeLog的路径,并在调用时将其映射到给定的更改日志。如果它们不相同,Liquibase将继续进行而不进行更改日志和警告。

所以在我从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)中运行 RollbackVisitor 时会发生这种情况。 ValidationVisitor 不会发生这种情况,因为 ChangeLogIterator 的创建方式不同,这就是为什么我没有收到任何错误\ warnings

答案 1 :(得分:0)

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

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

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

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

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

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

  • 如果从Web应用程序内部运行Liquibase,则Liquibase更改日志很可能位于类路径上,这意味着DATABASECHANGELOG表中的filename列前缀有classpath:< / p>

ID                  AUTHOR   FILENAME                                          
CreateWidgetTable   NabilH   classpath: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