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

Liquibase与PostgreSQL 10以下版本兼容性问题:serial与identity列

PostgreSQL bigserial 与 Identity 列的兼容问题

问题背景

我通过以下配置定义数据库列:

<column name="id" type="bigserial">
    <constraints primaryKey="true"/>
</column>

该配置在PostgreSQL 9.x版本中会生成独立序列及带默认值的列,但在PostgreSQL 15版本中生成的SQL语句变为:

id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL

技术问题与解答

1. 如何让该配置在所有PostgreSQL版本中都保持bigserial的行为?

  • 显式拆分序列与列的配置,替代bigserial的隐式映射:
    1. 单独定义序列:
      <sequence name="id_seq" startValue="1" incrementBy="1"/>
      
    2. 将列类型改为bigint,手动绑定序列的nextval作为默认值,同时保留主键约束:
      <column name="id" type="bigint" defaultValue="nextval('id_seq')">
          <constraints primaryKey="true" nullable="false"/>
      </column>
      
      这种写法在所有PostgreSQL版本中都会生成「独立序列+带默认值的bigint列」,完全匹配传统bigserial的行为。
  • 如果使用Hibernate等ORM框架,可以在实体类上通过@SequenceGenerator和@GeneratedValue(strategy = GenerationType.SEQUENCE)注解强制指定序列生成策略,避开不同PostgreSQL版本对bigserial的映射差异。

2. 能否不修改变更日志就将其恢复为bigserial?

可以,直接操作数据库元数据即可:

  1. 先创建符合bigserial默认规则的序列(命名格式通常为表名_id_seq):
    CREATE SEQUENCE 表名_id_seq OWNED BY 表名.id;
    
  2. 修改列的默认值为序列的nextval:
    ALTER TABLE 表名 ALTER COLUMN id SET DEFAULT nextval('表名_id_seq');
    
  3. 移除列的identity属性:
    ALTER TABLE 表名 ALTER COLUMN id DROP IDENTITY IF EXISTS;
    
    整个过程无需修改现有变更日志,直接在数据库端执行上述SQL就能将列恢复为bigserial的等效状态。

3. 在Spring Boot中需使用序列实现批量插入时,identity列有哪些优势?

  • 原生批量ID返回支持:PostgreSQL的identity列支持INSERT ... RETURNING语法批量返回生成的ID,Spring Data JPA或JDBC模板可直接利用该特性,无需手动预取序列值再插入,代码更简洁。
  • 事务安全无空洞:identity列的ID生成由数据库事务管理,不会出现手动预取序列值后事务回滚导致的序列空洞问题。
  • ORM优化更成熟:Spring Boot搭配的新版本Hibernate对PostgreSQL identity列的批量插入性能优化已接近序列方式,兼容性更好。
  • 减少对象维护成本:identity列的序列由数据库自动管理,无需手动创建、绑定序列对象,降低了数据库元数据的维护工作量。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 01:01:11