Liquibase:如何使用 CURRENT_TIMESTAMP 加载数据?
Liquibase: how to load data with CURRENT_TIMESTAMP?
我正在尝试更新我的项目,从
开始
<liquibase.version>3.5.5</liquibase.version>
<liquibase-hibernate5.version>3.6</liquibase-hibernate5.version>
到
<liquibase.version>3.9.0</liquibase.version>
<liquibase-hibernate5.version>3.8</liquibase-hibernate5.version>
我在从 CSV 文件加载数据时遇到了一些问题,这些文件包含一些以当前时间戳为值的列。
例如我的 CSV 文件:
id;name;created;modified
1;Book A;now();now()
2;Book B;now();now()
本书 table 是用以下内容创建的:
<createTable tableName="book">
<column name="id" type="bigint" autoIncrement="${autoIncrement}">
<constraints primaryKey="true" nullable="false"/>
</column>
<column name="name" type="varchar(255)">
<constraints nullable="false"/>
</column>
<column name="created" type="timestamp">
<constraints nullable="false"/>
</column>
<column name="modified" type="timestamp">
<constraints nullable="false"/>
</column>
</createTable>
数据加载为:
<property name="now" value="current_timestamp" dbms="postgresql"/>
<changeSet id="20180508144233-1" author="developer">
<loadData catalogName="public"
encoding="UTF-8"
file="config/liquibase/books.csv"
schemaName="public"
separator=";"
quotchar="'"
tableName="book">
</loadData>
</changeSet>
以前版本的 Liquibase 运行良好,但更新后出现以下错误:
2020-06-26 16:49:57 [project-Executor-1] [ERROR] liquibase.changelog.ChangeSet - Change Set config/liquibase/changelog/20180508144233_added_books_data.xml::20180508144233-1::developer failed. Error: liquibase.exception.DateParseException: Improper value in 'NOW' value: now(). 'NOW' must be followed by + or -, then numeric offset, then units (h{our{s}}, m{inute{s}}, d{ay{s}}, or y{ears}
Hibernate: select answerweig0_.id as id1_1_, answerweig0_.likelihood as likeliho2_1_, answerweig0_.question_type as question3_1_, answerweig0_.weight as weight4_1_ from answer_weight answerweig0_
2020-06-26 16:49:57 [project-Executor-1] [ERROR] i.g.j.c.l.AsyncSpringLiquibase - Liquibase could not start correctly, your database is NOT ready: Migration failed for change set config/liquibase/changelog/20180508144233_added_books_data.xml::20180508144233-1::developer:
Reason: liquibase.exception.UnexpectedLiquibaseException: liquibase.exception.DateParseException: Improper value in 'NOW' value: now(). 'NOW' must be followed by + or -, then numeric offset, then units (h{our{s}}, m{inute{s}}, d{ay{s}}, or y{ears}
liquibase.exception.MigrationFailedException: Migration failed for change set config/liquibase/changelog/20180508144233_added_books_data.xml::20180508144233-1::developer:
Reason: liquibase.exception.UnexpectedLiquibaseException: liquibase.exception.DateParseException: Improper value in 'NOW' value: now(). 'NOW' must be followed by + or -, then numeric offset, then units (h{our{s}}, m{inute{s}}, d{ay{s}}, or y{ears}
at liquibase.changelog.ChangeSet.execute(ChangeSet.java:646)
at liquibase.changelog.visitor.UpdateVisitor.visit(UpdateVisitor.java:53)
at liquibase.changelog.ChangeLogIterator.run(ChangeLogIterator.java:83)
at liquibase.Liquibase.update(Liquibase.java:202)
at liquibase.Liquibase.update(Liquibase.java:179)
at liquibase.integration.spring.SpringLiquibase.performUpdate(SpringLiquibase.java:366)
at liquibase.integration.spring.SpringLiquibase.afterPropertiesSet(SpringLiquibase.java:314)
at org.springframework.boot.autoconfigure.liquibase.DataSourceClosingSpringLiquibase.afterPropertiesSet(DataSourceClosingSpringLiquibase.java:46)
at io.github.jhipster.config.liquibase.AsyncSpringLiquibase.initDb(AsyncSpringLiquibase.java:118)
at io.github.jhipster.config.liquibase.AsyncSpringLiquibase.lambda$afterPropertiesSet[=16=](AsyncSpringLiquibase.java:93)
at io.github.jhipster.async.ExceptionHandlingAsyncTaskExecutor.lambda$createWrappedRunnable(ExceptionHandlingAsyncTaskExecutor.java:78)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
作为变通方法,我可以使用 table 创建更改日志中的默认值来设置此类列的值:
<createTable tableName="book">
<column name="id" type="bigint" autoIncrement="${autoIncrement}">
<constraints primaryKey="true" nullable="false"/>
</column>
<column name="name" type="varchar(255)">
<constraints nullable="false"/>
</column>
<column name="created" type="timestamp" defaultValueComputed="CURRENT_TIMESTAMP">
<constraints nullable="false"/>
</column>
<column name="modified" type="timestamp" defaultValueComputed="CURRENT_TIMESTAMP">
<constraints nullable="false"/>
</column>
</createTable>
并从 CSV 文件中删除相应的列:
id;name
1;Book A
2;Book B
但是,我仍在寻找将 CURRENT_TIMESTAMP 值保留在 CSV 文件中的方法。
您的解决方法非常正确。但是根据数据库的不同,您将必须添加一种方式,使您的 update_timestamp 或修改后的时间戳将根据您在此数据库行中的每次添加、减法或编辑而改变。例如,以下是如何在 PostgresSQL 中设置它。
<changeSet id="{UNIQUE_ID}" author="{YOUR_NAME}">
<preConditions onFail="MARK_RAN">
<dbms type="postgresql"/>
</preConditions>
<createProcedure>
CREATE OR REPLACE FUNCTION refresh_updated_date_column()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_date = now();
RETURN NEW;
END;
$$ language 'plpgsql';
</createProcedure>
<rollback>
DROP FUNCTION IF EXISTS refresh_updated_date_column;
</rollback>
</changeSet>`
这将是您将在创建 table 并添加所需列的原始变更集之后添加的附加变更集。
我正在尝试更新我的项目,从
开始 <liquibase.version>3.5.5</liquibase.version>
<liquibase-hibernate5.version>3.6</liquibase-hibernate5.version>
到
<liquibase.version>3.9.0</liquibase.version>
<liquibase-hibernate5.version>3.8</liquibase-hibernate5.version>
我在从 CSV 文件加载数据时遇到了一些问题,这些文件包含一些以当前时间戳为值的列。
例如我的 CSV 文件:
id;name;created;modified
1;Book A;now();now()
2;Book B;now();now()
本书 table 是用以下内容创建的:
<createTable tableName="book">
<column name="id" type="bigint" autoIncrement="${autoIncrement}">
<constraints primaryKey="true" nullable="false"/>
</column>
<column name="name" type="varchar(255)">
<constraints nullable="false"/>
</column>
<column name="created" type="timestamp">
<constraints nullable="false"/>
</column>
<column name="modified" type="timestamp">
<constraints nullable="false"/>
</column>
</createTable>
数据加载为:
<property name="now" value="current_timestamp" dbms="postgresql"/>
<changeSet id="20180508144233-1" author="developer">
<loadData catalogName="public"
encoding="UTF-8"
file="config/liquibase/books.csv"
schemaName="public"
separator=";"
quotchar="'"
tableName="book">
</loadData>
</changeSet>
以前版本的 Liquibase 运行良好,但更新后出现以下错误:
2020-06-26 16:49:57 [project-Executor-1] [ERROR] liquibase.changelog.ChangeSet - Change Set config/liquibase/changelog/20180508144233_added_books_data.xml::20180508144233-1::developer failed. Error: liquibase.exception.DateParseException: Improper value in 'NOW' value: now(). 'NOW' must be followed by + or -, then numeric offset, then units (h{our{s}}, m{inute{s}}, d{ay{s}}, or y{ears}
Hibernate: select answerweig0_.id as id1_1_, answerweig0_.likelihood as likeliho2_1_, answerweig0_.question_type as question3_1_, answerweig0_.weight as weight4_1_ from answer_weight answerweig0_
2020-06-26 16:49:57 [project-Executor-1] [ERROR] i.g.j.c.l.AsyncSpringLiquibase - Liquibase could not start correctly, your database is NOT ready: Migration failed for change set config/liquibase/changelog/20180508144233_added_books_data.xml::20180508144233-1::developer:
Reason: liquibase.exception.UnexpectedLiquibaseException: liquibase.exception.DateParseException: Improper value in 'NOW' value: now(). 'NOW' must be followed by + or -, then numeric offset, then units (h{our{s}}, m{inute{s}}, d{ay{s}}, or y{ears}
liquibase.exception.MigrationFailedException: Migration failed for change set config/liquibase/changelog/20180508144233_added_books_data.xml::20180508144233-1::developer:
Reason: liquibase.exception.UnexpectedLiquibaseException: liquibase.exception.DateParseException: Improper value in 'NOW' value: now(). 'NOW' must be followed by + or -, then numeric offset, then units (h{our{s}}, m{inute{s}}, d{ay{s}}, or y{ears}
at liquibase.changelog.ChangeSet.execute(ChangeSet.java:646)
at liquibase.changelog.visitor.UpdateVisitor.visit(UpdateVisitor.java:53)
at liquibase.changelog.ChangeLogIterator.run(ChangeLogIterator.java:83)
at liquibase.Liquibase.update(Liquibase.java:202)
at liquibase.Liquibase.update(Liquibase.java:179)
at liquibase.integration.spring.SpringLiquibase.performUpdate(SpringLiquibase.java:366)
at liquibase.integration.spring.SpringLiquibase.afterPropertiesSet(SpringLiquibase.java:314)
at org.springframework.boot.autoconfigure.liquibase.DataSourceClosingSpringLiquibase.afterPropertiesSet(DataSourceClosingSpringLiquibase.java:46)
at io.github.jhipster.config.liquibase.AsyncSpringLiquibase.initDb(AsyncSpringLiquibase.java:118)
at io.github.jhipster.config.liquibase.AsyncSpringLiquibase.lambda$afterPropertiesSet[=16=](AsyncSpringLiquibase.java:93)
at io.github.jhipster.async.ExceptionHandlingAsyncTaskExecutor.lambda$createWrappedRunnable(ExceptionHandlingAsyncTaskExecutor.java:78)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
作为变通方法,我可以使用 table 创建更改日志中的默认值来设置此类列的值:
<createTable tableName="book">
<column name="id" type="bigint" autoIncrement="${autoIncrement}">
<constraints primaryKey="true" nullable="false"/>
</column>
<column name="name" type="varchar(255)">
<constraints nullable="false"/>
</column>
<column name="created" type="timestamp" defaultValueComputed="CURRENT_TIMESTAMP">
<constraints nullable="false"/>
</column>
<column name="modified" type="timestamp" defaultValueComputed="CURRENT_TIMESTAMP">
<constraints nullable="false"/>
</column>
</createTable>
并从 CSV 文件中删除相应的列:
id;name
1;Book A
2;Book B
但是,我仍在寻找将 CURRENT_TIMESTAMP 值保留在 CSV 文件中的方法。
您的解决方法非常正确。但是根据数据库的不同,您将必须添加一种方式,使您的 update_timestamp 或修改后的时间戳将根据您在此数据库行中的每次添加、减法或编辑而改变。例如,以下是如何在 PostgresSQL 中设置它。
<changeSet id="{UNIQUE_ID}" author="{YOUR_NAME}">
<preConditions onFail="MARK_RAN">
<dbms type="postgresql"/>
</preConditions>
<createProcedure>
CREATE OR REPLACE FUNCTION refresh_updated_date_column()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_date = now();
RETURN NEW;
END;
$$ language 'plpgsql';
</createProcedure>
<rollback>
DROP FUNCTION IF EXISTS refresh_updated_date_column;
</rollback>
</changeSet>`
这将是您将在创建 table 并添加所需列的原始变更集之后添加的附加变更集。