从命令行回滚 Liquibase 不起作用
Liquibase rollback from command line not working
我正在 windows 环境中执行 tomcat 应用程序,当部署时 creates/updates 数据库架构在 oracle 数据库上。为此,我使用 Liquibase SDK 3.3.2。所以基本上我调用 SDK 并告诉它从我的 changelog.xml 进行更新。这部分工作正常。
代码形式 java class
...
Liquibase liquibase = new Liquibase(CHANGE_LOG,
new ClassLoaderResourceAccessor(getClass().getClassLoader()), db);
liquibase.update("");
问题是,当出现问题并且我从命令行执行回滚时,什么也没有发生。我没有收到任何异常或错误消息。只是一条消息 "Rollback succesfull",但在数据库中根本没有任何变化。现在有趣的是,当我从 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 工具之间是否存在不兼容问题?
问题出在更改日志文件的路径上。 Liquibase 在某处存储到 chengeLog 的路径,并在调用时将其映射到给定的更改日志。如果它们不相同,Liquibase 将在没有更改日志和警告的情况下继续进行。
所以在我的例子中,当从 tomcat 应用程序调用 Liquibase 时,路径是:database\master.xml 并且从控制台我在命令行中给出了路径 C:\myProject\src\main\resources\database\master.xml 。这导致该方法为 return null,尽管 Liquibase 知道更改日志的路径。所以这就是它不起作用的原因。
解决方法 是从与应用程序使用相对路径相同的文件夹的命令行调用 liquibase。
技术原因:
在 debuggin LB 之后我发现了这个。方法 DatabaseChageLog.getChangeSet() 是 returning null 尽管 changeLog 路径是正确的。在方法 Liquibase.rollback(int changesToRollback, Contexts contexts, LabelExpression labelExpression)。 ValidationVisitor 不会发生这种情况,因为 ChangeLogIterator 的创建方式不同,这就是为什么我没有得到任何 error\warnings [=10] =]
为了其他读者的利益,我想补充一下我的经验和理解。
了解当您运行从命令行
回滚时发生的事情很重要
Liquibase 参考您通过 --changeLogFile
参数提供的变更日志文件。
它将遍历此文件中提到的变更集,将它们的校验和与 DATABASECHANGELOG
数据库 table.
中相应记录的校验和进行比较
现在重要的一点是:校验和是根据文件名(包括路径)和文件内容计算的。
如果校验和不匹配,则变更集不符合回滚条件。
如果您从 Web 应用程序内部 运行 Liquibase,Liquibase 变更日志很可能位于类路径中,这意味着 DATABASECHANGELOG
table 以类路径为前缀:
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
我正在 windows 环境中执行 tomcat 应用程序,当部署时 creates/updates 数据库架构在 oracle 数据库上。为此,我使用 Liquibase SDK 3.3.2。所以基本上我调用 SDK 并告诉它从我的 changelog.xml 进行更新。这部分工作正常。 代码形式 java class
...
Liquibase liquibase = new Liquibase(CHANGE_LOG,
new ClassLoaderResourceAccessor(getClass().getClassLoader()), db);
liquibase.update("");
问题是,当出现问题并且我从命令行执行回滚时,什么也没有发生。我没有收到任何异常或错误消息。只是一条消息 "Rollback succesfull",但在数据库中根本没有任何变化。现在有趣的是,当我从 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 工具之间是否存在不兼容问题?
问题出在更改日志文件的路径上。 Liquibase 在某处存储到 chengeLog 的路径,并在调用时将其映射到给定的更改日志。如果它们不相同,Liquibase 将在没有更改日志和警告的情况下继续进行。
所以在我的例子中,当从 tomcat 应用程序调用 Liquibase 时,路径是:database\master.xml 并且从控制台我在命令行中给出了路径 C:\myProject\src\main\resources\database\master.xml 。这导致该方法为 return null,尽管 Liquibase 知道更改日志的路径。所以这就是它不起作用的原因。
解决方法 是从与应用程序使用相对路径相同的文件夹的命令行调用 liquibase。
技术原因: 在 debuggin LB 之后我发现了这个。方法 DatabaseChageLog.getChangeSet() 是 returning null 尽管 changeLog 路径是正确的。在方法 Liquibase.rollback(int changesToRollback, Contexts contexts, LabelExpression labelExpression)。 ValidationVisitor 不会发生这种情况,因为 ChangeLogIterator 的创建方式不同,这就是为什么我没有得到任何 error\warnings [=10] =]
为了其他读者的利益,我想补充一下我的经验和理解。
了解当您运行从命令行
回滚时发生的事情很重要Liquibase 参考您通过
--changeLogFile
参数提供的变更日志文件。它将遍历此文件中提到的变更集,将它们的校验和与
中相应记录的校验和进行比较DATABASECHANGELOG
数据库 table.现在重要的一点是:校验和是根据文件名(包括路径)和文件内容计算的。
如果校验和不匹配,则变更集不符合回滚条件。
如果您从 Web 应用程序内部 运行 Liquibase,Liquibase 变更日志很可能位于类路径中,这意味着
DATABASECHANGELOG
table 以类路径为前缀:
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