Liquibase Java,变更集不适用
Liquibase Java, changesets don't apply
我目前正在为我的实习构建一个项目,但自从两天尝试在 java 中使用 Liquibase 以来我就卡住了。一切似乎都是正确的:找到了更改日志文件,正确的 URI、用户名和密码;但是当我 运行 它时,我的变更集没有被处理。
我使用这个 class 来管理程序中的 liquibase 操作,例如 rollback、update、updateSQL 和 futureRollbackSQL,给定一个变更日志,最终是一个目标文件。如果源或目标来自远程服务器,我使用一些 SSH 交互(scp to,scp from)与 JSch 和临时文件(但这不是主题)。
这是我目前的 java 代码,给定 db、user、passwd 、realAction是前面设置的,changelogpath和dest是一些数据存储class.
Connection c = null;
Database database = null;
PrintWriter pw = null;
File file = null;
liquibase.Liquibase liquibase = null;
contexts = db+"."+user;
try {
pw = new PrintWriter(new FileWriter(file));
// Get connection
c = SQLManager.getInstance().getConnection(db, user, passwd);
// Get liquibase connection
database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(new JdbcConnection(c));
liquibase = new liquibase.Liquibase(new DatabaseChangeLog(fsource), new FileSystemResourceAccessor(),
database);
// Run liquibase action
switch (realAction) {
case Constants.LIQUIBASE_ACTION_FUTUREROLLBACKSQL:
liquibase.futureRollbackSQL(pw);
break;
case Constants.LIQUIBASE_ACTION_UPDATESQL:
liquibase.update(contexts, pw);
break;
case Constants.LIQUIBASE_ACTION_UPDATE:
liquibase.update(contexts);
if (!c.getAutoCommit())
c.commit();
break;
default:
throw new OdewipElementRuntimeException(this, "Action not implemented");
}
pw.close();
database.close();
c.close();
} catch (IOException | SQLException | LiquibaseException e) {
throw new Exception(e.getMessage());
} finally {
if (c != null) {
try {
c.close();
} catch (SQLException e) {
// nothing to do
throw new RuntimeException(e.getClass() + ": " + e.getMessage());
}
}
}
这是我的更新日志:
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ora="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-2.0.xsd http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd">
<changeSet id="mychangeset" author="testy">
<preConditions onSqlOutput="TEST" onFail="MARK_RAN">
<not>
<tableExists tableName="abcd"/>
</not>
</preConditions>
<createTable tableName="abcd">
<column name="id" type="number">
<constraints primaryKey="true"/>
</column>
</createTable>
</changeSet>
</databaseChangeLog>
Liquibase 似乎可以做 一些事情,除了解析我的变更集。当我启动我的操作时,sql 生成的文件仅包含两个 table liquibase(databasechangelog 和 databasechangeloglock)的创建,仅此而已。 update 操作根本不会修改任何内容(甚至不会创建前面提到的两个 tables)。我(100%)确定 table abcd 在执行前不存在于数据库中。
所以我想我现在需要一些帮助,以找出不起作用的地方。我试图查看 liquibase 论坛中的一些示例,但没有任何帮助。
我目前正在使用 Maven 的 liquibase 3.4.0:
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
<version>3.4.0</version>
</dependency>
还有我遗漏的依赖项吗?
另一个小问题是如何包含一个特殊的 oracle 数据库驱动程序 (ojdbc6.jar)?
感谢您的回答。
编辑 2015 年 6 月 8 日:
我在调试模式下得到了日志(故意更改了架构名称):
DEBUG 06/08/15 09:28: liquibase: Executing QUERY database command: select count(*) from MYSCHEMA.DATABASECHANGELOGLOCK
DEBUG 06/08/15 09:28: liquibase: Create Database Lock Table
DEBUG 06/08/15 09:28: liquibase: Executing EXECUTE database command: CREATE TABLE MYSCHEMA.DATABASECHANGELOGLOCK (ID NUMBER(10) NOT NULL, LOCKED NUMBER(1) NOT NULL, LOCKGRANTED TIMESTAMP, LOCKEDBY VARCHAR2(255), CONSTRAINT PK_DATABASECHANGELOGLOCK PRIMARY KEY (ID))
DEBUG 06/08/15 09:28: liquibase: Created database lock table with name: MYSCHEMA.DATABASECHANGELOGLOCK
DEBUG 06/08/15 09:28: liquibase: Executing QUERY database command: select count(*) from MYSCHEMA.DATABASECHANGELOGLOCK
DEBUG 06/08/15 09:28: liquibase: Initialize Database Lock Table
DEBUG 06/08/15 09:28: liquibase: Executing EXECUTE database command: DELETE FROM MYSCHEMA.DATABASECHANGELOGLOCK
DEBUG 06/08/15 09:28: liquibase: Executing EXECUTE database command: INSERT INTO MYSCHEMA.DATABASECHANGELOGLOCK (ID, LOCKED) VALUES (1, 0)
DEBUG 06/08/15 09:28: liquibase: Executing QUERY database command: SELECT LOCKED FROM MYSCHEMA.DATABASECHANGELOGLOCK WHERE ID=1 FOR UPDATE
DEBUG 06/08/15 09:28: liquibase: Lock Database
DEBUG 06/08/15 09:28: liquibase: Executing UPDATE database command: UPDATE MYSCHEMA.DATABASECHANGELOGLOCK SET LOCKED = 1, LOCKEDBY = 'CRO09177 (xx.xx.xx.xxx)', LOCKGRANTED = to_date('2015-08-06 09:28:28', 'YYYY-MM-DD HH24:MI:SS') WHERE ID = 1 AND LOCKED = 0
INFO 06/08/15 09:28: liquibase: Successfully acquired change log lock
DEBUG 06/08/15 09:28: liquibase: Create Database Change Log Table
INFO 06/08/15 09:28: liquibase: Creating database history table with name: MYSCHEMA.DATABASECHANGELOG
DEBUG 06/08/15 09:28: liquibase: Executing EXECUTE database command: CREATE TABLE MYSCHEMA.DATABASECHANGELOG (ID VARCHAR2(255) NOT NULL, AUTHOR VARCHAR2(255) NOT NULL, FILENAME VARCHAR2(255) NOT NULL, DATEEXECUTED TIMESTAMP NOT NULL, ORDEREXECUTED NUMBER(10) NOT NULL, EXECTYPE VARCHAR2(10) NOT NULL, MD5SUM VARCHAR2(35), DESCRIPTION VARCHAR2(255), COMMENTS VARCHAR2(255), TAG VARCHAR2(255), LIQUIBASE VARCHAR2(20), CONTEXTS VARCHAR2(255), LABELS VARCHAR2(255))
DEBUG 06/08/15 09:28: liquibase: Executing QUERY database command: select count(*) from MYSCHEMA.DATABASECHANGELOG
INFO 06/08/15 09:28: liquibase: Reading from MYSCHEMA.DATABASECHANGELOG
DEBUG 06/08/15 09:28: liquibase: Executing QUERY database command: SELECT FILENAME,AUTHOR,ID,MD5SUM,DATEEXECUTED,ORDEREXECUTED,EXECTYPE,DESCRIPTION,COMMENTS,TAG,LIQUIBASE,LABELS,CONTEXTS FROM MYSCHEMA.DATABASECHANGELOG ORDER BY DATEEXECUTED ASC, ORDEREXECUTED ASC
DEBUG 06/08/15 09:28: liquibase: Executing QUERY database command: select count(*) from MYSCHEMA.DATABASECHANGELOGLOCK
DEBUG 06/08/15 09:28: liquibase: Release Database Lock
DEBUG 06/08/15 09:28: liquibase: Executing UPDATE database command: UPDATE MYSCHEMA.DATABASECHANGELOGLOCK SET LOCKED = 0, LOCKEDBY = NULL, LOCKGRANTED = NULL WHERE ID = 1
INFO 06/08/15 09:28: liquibase: Successfully released change log lock
在 Datical,我们注意到 Liquibase 和 Java 1.8 存在一些问题。您在 post 上向 Liquibase 用户论坛提到您使用的是 Java 1.8,因此 Java 1.8 可能是问题所在。您可以尝试使用 Java 1.7 看看是否会得到不同的结果吗?如果没有,您可以尝试提高日志记录级别 - 在创建 Liquibase 对象后添加如下一行:
LogFactory.getInstance().getLog().setLogLevel(logLevel);
其中 logLevel 是字符串 "debug"
很可能是 XML 版本的问题。
替换为 XML header
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-2.0.xsd
到
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.4.xsd
我遇到了同样的问题,即使这个问题真的很老,我也会尽量给出答案。代码有两点错误:
- 变更集路径
PrintWriter
如果路径不可读,Liquibase API 不会给出良好的反馈,但通常,您会在没有任何应用查询的情况下看到日志记录锁定。
此外,在您的代码中,执行打印在 Writer 中而不是执行查询。
在这里您可以找到一个工作示例:
Database database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(new JdbcConnection(ds.getConnection()));
Liquibase liquibase = new Liquibase("./relativepathToChangeset", new FileSystemResourceAccessor(new File("basePathWhereChangeSetIsPresent")), database);
liquibase.update("");
我正在分享我找到的解决方案,用于修复 运行 liquibase update
时未应用的更改。请注意,我没有使用 Java,我将更新日志作为 .sql
文件进行管理。我正在使用 Snowflake JDBC 驱动程序。为我修复它的是在 liquibase.properties
文件中明确定义 defaultCatalogName
和 defaultSchemaName
属性。仅在 JDBC url 中提供这些参数是不够的。我的 liquibase.properties
文件如下所示:
changeLogFile: sql/changelog.sql
url: jdbc:snowflake://<url>?db=<database name>&schema=PUBLIC&role=SYSADMIN&warehouse=COMPUTE_WH
driver: net.snowflake.client.jdbc.SnowflakeDriver
username: <username>
password: <password>
classpath: snowflake-jdbc-3.13.14.jar
defaultCatalogName: <database name>
defaultSchemaName: PUBLIC
liquibase.hub.mode=off
我希望这对像我一样遇到这个 Whosebug post 的人有所帮助。
我目前正在为我的实习构建一个项目,但自从两天尝试在 java 中使用 Liquibase 以来我就卡住了。一切似乎都是正确的:找到了更改日志文件,正确的 URI、用户名和密码;但是当我 运行 它时,我的变更集没有被处理。
我使用这个 class 来管理程序中的 liquibase 操作,例如 rollback、update、updateSQL 和 futureRollbackSQL,给定一个变更日志,最终是一个目标文件。如果源或目标来自远程服务器,我使用一些 SSH 交互(scp to,scp from)与 JSch 和临时文件(但这不是主题)。
这是我目前的 java 代码,给定 db、user、passwd 、realAction是前面设置的,changelogpath和dest是一些数据存储class.
Connection c = null;
Database database = null;
PrintWriter pw = null;
File file = null;
liquibase.Liquibase liquibase = null;
contexts = db+"."+user;
try {
pw = new PrintWriter(new FileWriter(file));
// Get connection
c = SQLManager.getInstance().getConnection(db, user, passwd);
// Get liquibase connection
database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(new JdbcConnection(c));
liquibase = new liquibase.Liquibase(new DatabaseChangeLog(fsource), new FileSystemResourceAccessor(),
database);
// Run liquibase action
switch (realAction) {
case Constants.LIQUIBASE_ACTION_FUTUREROLLBACKSQL:
liquibase.futureRollbackSQL(pw);
break;
case Constants.LIQUIBASE_ACTION_UPDATESQL:
liquibase.update(contexts, pw);
break;
case Constants.LIQUIBASE_ACTION_UPDATE:
liquibase.update(contexts);
if (!c.getAutoCommit())
c.commit();
break;
default:
throw new OdewipElementRuntimeException(this, "Action not implemented");
}
pw.close();
database.close();
c.close();
} catch (IOException | SQLException | LiquibaseException e) {
throw new Exception(e.getMessage());
} finally {
if (c != null) {
try {
c.close();
} catch (SQLException e) {
// nothing to do
throw new RuntimeException(e.getClass() + ": " + e.getMessage());
}
}
}
这是我的更新日志:
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ora="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-2.0.xsd http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd">
<changeSet id="mychangeset" author="testy">
<preConditions onSqlOutput="TEST" onFail="MARK_RAN">
<not>
<tableExists tableName="abcd"/>
</not>
</preConditions>
<createTable tableName="abcd">
<column name="id" type="number">
<constraints primaryKey="true"/>
</column>
</createTable>
</changeSet>
</databaseChangeLog>
Liquibase 似乎可以做 一些事情,除了解析我的变更集。当我启动我的操作时,sql 生成的文件仅包含两个 table liquibase(databasechangelog 和 databasechangeloglock)的创建,仅此而已。 update 操作根本不会修改任何内容(甚至不会创建前面提到的两个 tables)。我(100%)确定 table abcd 在执行前不存在于数据库中。
所以我想我现在需要一些帮助,以找出不起作用的地方。我试图查看 liquibase 论坛中的一些示例,但没有任何帮助。 我目前正在使用 Maven 的 liquibase 3.4.0:
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
<version>3.4.0</version>
</dependency>
还有我遗漏的依赖项吗? 另一个小问题是如何包含一个特殊的 oracle 数据库驱动程序 (ojdbc6.jar)?
感谢您的回答。
编辑 2015 年 6 月 8 日: 我在调试模式下得到了日志(故意更改了架构名称):
DEBUG 06/08/15 09:28: liquibase: Executing QUERY database command: select count(*) from MYSCHEMA.DATABASECHANGELOGLOCK
DEBUG 06/08/15 09:28: liquibase: Create Database Lock Table
DEBUG 06/08/15 09:28: liquibase: Executing EXECUTE database command: CREATE TABLE MYSCHEMA.DATABASECHANGELOGLOCK (ID NUMBER(10) NOT NULL, LOCKED NUMBER(1) NOT NULL, LOCKGRANTED TIMESTAMP, LOCKEDBY VARCHAR2(255), CONSTRAINT PK_DATABASECHANGELOGLOCK PRIMARY KEY (ID))
DEBUG 06/08/15 09:28: liquibase: Created database lock table with name: MYSCHEMA.DATABASECHANGELOGLOCK
DEBUG 06/08/15 09:28: liquibase: Executing QUERY database command: select count(*) from MYSCHEMA.DATABASECHANGELOGLOCK
DEBUG 06/08/15 09:28: liquibase: Initialize Database Lock Table
DEBUG 06/08/15 09:28: liquibase: Executing EXECUTE database command: DELETE FROM MYSCHEMA.DATABASECHANGELOGLOCK
DEBUG 06/08/15 09:28: liquibase: Executing EXECUTE database command: INSERT INTO MYSCHEMA.DATABASECHANGELOGLOCK (ID, LOCKED) VALUES (1, 0)
DEBUG 06/08/15 09:28: liquibase: Executing QUERY database command: SELECT LOCKED FROM MYSCHEMA.DATABASECHANGELOGLOCK WHERE ID=1 FOR UPDATE
DEBUG 06/08/15 09:28: liquibase: Lock Database
DEBUG 06/08/15 09:28: liquibase: Executing UPDATE database command: UPDATE MYSCHEMA.DATABASECHANGELOGLOCK SET LOCKED = 1, LOCKEDBY = 'CRO09177 (xx.xx.xx.xxx)', LOCKGRANTED = to_date('2015-08-06 09:28:28', 'YYYY-MM-DD HH24:MI:SS') WHERE ID = 1 AND LOCKED = 0
INFO 06/08/15 09:28: liquibase: Successfully acquired change log lock
DEBUG 06/08/15 09:28: liquibase: Create Database Change Log Table
INFO 06/08/15 09:28: liquibase: Creating database history table with name: MYSCHEMA.DATABASECHANGELOG
DEBUG 06/08/15 09:28: liquibase: Executing EXECUTE database command: CREATE TABLE MYSCHEMA.DATABASECHANGELOG (ID VARCHAR2(255) NOT NULL, AUTHOR VARCHAR2(255) NOT NULL, FILENAME VARCHAR2(255) NOT NULL, DATEEXECUTED TIMESTAMP NOT NULL, ORDEREXECUTED NUMBER(10) NOT NULL, EXECTYPE VARCHAR2(10) NOT NULL, MD5SUM VARCHAR2(35), DESCRIPTION VARCHAR2(255), COMMENTS VARCHAR2(255), TAG VARCHAR2(255), LIQUIBASE VARCHAR2(20), CONTEXTS VARCHAR2(255), LABELS VARCHAR2(255))
DEBUG 06/08/15 09:28: liquibase: Executing QUERY database command: select count(*) from MYSCHEMA.DATABASECHANGELOG
INFO 06/08/15 09:28: liquibase: Reading from MYSCHEMA.DATABASECHANGELOG
DEBUG 06/08/15 09:28: liquibase: Executing QUERY database command: SELECT FILENAME,AUTHOR,ID,MD5SUM,DATEEXECUTED,ORDEREXECUTED,EXECTYPE,DESCRIPTION,COMMENTS,TAG,LIQUIBASE,LABELS,CONTEXTS FROM MYSCHEMA.DATABASECHANGELOG ORDER BY DATEEXECUTED ASC, ORDEREXECUTED ASC
DEBUG 06/08/15 09:28: liquibase: Executing QUERY database command: select count(*) from MYSCHEMA.DATABASECHANGELOGLOCK
DEBUG 06/08/15 09:28: liquibase: Release Database Lock
DEBUG 06/08/15 09:28: liquibase: Executing UPDATE database command: UPDATE MYSCHEMA.DATABASECHANGELOGLOCK SET LOCKED = 0, LOCKEDBY = NULL, LOCKGRANTED = NULL WHERE ID = 1
INFO 06/08/15 09:28: liquibase: Successfully released change log lock
在 Datical,我们注意到 Liquibase 和 Java 1.8 存在一些问题。您在 post 上向 Liquibase 用户论坛提到您使用的是 Java 1.8,因此 Java 1.8 可能是问题所在。您可以尝试使用 Java 1.7 看看是否会得到不同的结果吗?如果没有,您可以尝试提高日志记录级别 - 在创建 Liquibase 对象后添加如下一行:
LogFactory.getInstance().getLog().setLogLevel(logLevel);
其中 logLevel 是字符串 "debug"
很可能是 XML 版本的问题。
替换为 XML header
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-2.0.xsd
到
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.4.xsd
我遇到了同样的问题,即使这个问题真的很老,我也会尽量给出答案。代码有两点错误:
- 变更集路径
PrintWriter
如果路径不可读,Liquibase API 不会给出良好的反馈,但通常,您会在没有任何应用查询的情况下看到日志记录锁定。
此外,在您的代码中,执行打印在 Writer 中而不是执行查询。
在这里您可以找到一个工作示例:
Database database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(new JdbcConnection(ds.getConnection()));
Liquibase liquibase = new Liquibase("./relativepathToChangeset", new FileSystemResourceAccessor(new File("basePathWhereChangeSetIsPresent")), database);
liquibase.update("");
我正在分享我找到的解决方案,用于修复 运行 liquibase update
时未应用的更改。请注意,我没有使用 Java,我将更新日志作为 .sql
文件进行管理。我正在使用 Snowflake JDBC 驱动程序。为我修复它的是在 liquibase.properties
文件中明确定义 defaultCatalogName
和 defaultSchemaName
属性。仅在 JDBC url 中提供这些参数是不够的。我的 liquibase.properties
文件如下所示:
changeLogFile: sql/changelog.sql
url: jdbc:snowflake://<url>?db=<database name>&schema=PUBLIC&role=SYSADMIN&warehouse=COMPUTE_WH
driver: net.snowflake.client.jdbc.SnowflakeDriver
username: <username>
password: <password>
classpath: snowflake-jdbc-3.13.14.jar
defaultCatalogName: <database name>
defaultSchemaName: PUBLIC
liquibase.hub.mode=off
我希望这对像我一样遇到这个 Whosebug post 的人有所帮助。