You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Liquibase+H2DB测试报错:无法解析TIMESTAMP常量${now}

解决Liquibase在H2DB中${now}属性解析失败的问题

我之前也踩过一模一样的坑——PostgreSQL下Liquibase跑得顺风顺水,一到H2DB测试就因为${now}没被正确替换报错,折腾了好几天才摸清楚几个靠谱的解决办法,分享给你:

1. 改用Liquibase的defaultValueComputed属性

这是最省心的方案!直接把变更集里的defaultValue="${now}"换成defaultValueComputed="${now}",Liquibase会自动根据数据库类型,把${now}转换成对应的原生时间函数:

  • PostgreSQL下生成DEFAULT NOW()
  • H2DB下生成DEFAULT CURRENT_TIMESTAMP

修改后的变更集示例:

<?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"
                   xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
                   http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.9.xsd">
    <changeSet id="create_test_table" author="your-name">
        <createTable tableName="test_table">
            <column name="id" type="BIGINT" autoIncrement="true">
                <constraints primaryKey="true"/>
            </column>
            <!-- 改用defaultValueComputed适配多数据库 -->
            <column name="created_at" type="TIMESTAMP" defaultValueComputed="${now}"/>
        </createTable>
    </changeSet>
</databaseChangeLog>

2. 开启H2DB的PostgreSQL兼容模式

如果不想改变更集,那就让H2DB模拟PostgreSQL的行为,这样它就能直接识别NOW()函数。只需要在测试的JDBC连接URL里加上MODE=PostgreSQL参数:

jdbc:h2:mem:testdb;MODE=PostgreSQL;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=false

这样Liquibase把${now}替换成NOW()后,H2DB就能正常解析,和PostgreSQL环境保持一致。

3. 为H2DB显式定义now属性

在测试环境的Liquibase配置文件(比如liquibase-test.properties)里,直接给now属性指定H2能识别的值:

now=CURRENT_TIMESTAMP

这样Liquibase在H2环境下会自动把${now}替换成CURRENT_TIMESTAMP,完美适配H2的语法。

4. 用上下文区分数据库(备选方案)

如果以上方法都不适用,可以给不同数据库写单独的变更集,用Liquibase的context和dbms预条件区分:

<!-- PostgreSQL专用变更集 -->
<changeSet id="create_table_pg" author="your-name">
    <preConditions onFail="MARK_RAN">
        <dbms type="postgresql"/>
    </preConditions>
    <sql>
        CREATE TABLE test_table (
            id BIGINT AUTO_INCREMENT PRIMARY KEY,
            created_at TIMESTAMP DEFAULT NOW()
        )
    </sql>
</changeSet>

<!-- H2专用变更集 -->
<changeSet id="create_table_h2" author="your-name" context="test">
    <preConditions onFail="MARK_RAN">
        <dbms type="h2"/>
    </preConditions>
    <sql>
        CREATE TABLE test_table (
            id BIGINT AUTO_INCREMENT PRIMARY KEY,
            created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
        )
    </sql>
</changeSet>

不过这个方案会增加维护成本,除非特殊情况不推荐使用。

亲测前三个方法都能解决问题,优先推荐前两个,既能保持变更集的通用性又不用额外配置太多~

内容的提问来源于stack exchange,提问作者1Z10

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 08:42:38