模拟PostgreSQL的H2数据库无法创建auto_increment字段求助
问题场景
使用H2数据库并启用PostgreSQL兼容模式,JDBC URL:
jdbc:h2:~/test;MODE=PostgreSQL;DATABASE_TO_LOWER=TRUE;DEFAULT_NULL_ORDERING=HIGH
执行创建自增字段的SQL时报错:
create table test(id bigint auto_increment);
报错信息:
Syntax error in SQL statement "create table test(id bigint [*]auto_increment)"; expected "ARRAY, INVISIBLE, VISIBLE, NOT NULL, NULL, AS, DEFAULT, GENERATED, ON UPDATE, NOT NULL, NULL, DEFAULT ON NULL, NULL_TO_DEFAULT, SEQUENCE, SELECTIVITY, COMMENT, CONSTRAINT, COMMENT, PRIMARY KEY, UNIQUE, NOT NULL, NULL, CHECK, REFERENCES, ,, )"; SQL statement:
create table test(id bigint auto_increment) [42001-214] 42001/42001 (Help)
背景:基于JPA/Hibernate+Liquibase的项目中出现NULL not allowed for column "REV"错误,需要通过在Liquibase changelog中添加自增字段解决。
解决方案
1. 直接使用H2 PostgreSQL兼容模式支持的自增语法
在PostgreSQL兼容模式下,H2不识别auto_increment关键字,也不完全兼容PostgreSQL的serial类型,需使用SQL标准的自增定义方式:
create table test(id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY);
如果需要强制自增(禁止手动插入值),可以改用:
create table test(id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY);
2. 在Liquibase Changelog中配置自增字段
针对Liquibase场景,推荐使用数据库无关的配置方式,避免直接写SQL带来的兼容性问题:
<changeSet id="create-test-table" author="your-name"> <createTable tableName="test"> <column name="id" type="BIGINT" autoIncrement="true"> <constraints primaryKey="true" nullable="false"/> </column> </createTable> </changeSet>
Liquibase会根据目标数据库(H2 PostgreSQL模式)自动生成对应自增语法,同时解决REV字段非空的问题。
如果必须使用自定义SQL,可通过dbms属性区分数据库:
<changeSet id="create-test-table" author="your-name"> <sql dbms="h2"> create table test(id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY); </sql> <sql dbms="postgresql"> create table test(id bigserial PRIMARY KEY); </sql> </changeSet>
3. 额外注意事项
- 确保H2版本与Liquibase、Hibernate的版本兼容,避免因版本差异导致的语法支持问题;
- 检查Hibernate方言配置,对于H2 PostgreSQL模式,建议设置为
org.hibernate.dialect.H2Dialect,部分场景下org.hibernate.dialect.PostgreSQLDialect也可兼容,但需提前测试。
内容的提问来源于stack exchange,提问作者Woodsman

