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

接入Flyway后PostgreSQL测试数据导致自增ID失效重复主键报错

问题原因
  1. PostgreSQL的自增主键依赖序列对象实现,未指定策略的@GeneratedValue注解在PostgreSQL方言下,Hibernate默认会使用名为hibernate_sequence的全局序列生成主键,序列初始值为1。
  2. 接入Flyway前,spring.jpa.hibernate.ddl-auto=update配置会自动处理主键的自增关联逻辑,插入数据时Hibernate生成ID会同步推进序列值,所以ID可以正常递增。
  3. 接入Flyway后,你手动编写的建表语句没有给id字段设置自增属性(如serial8/GENERATED AS IDENTITY),手动插入ID=1、2、3的测试数据时不会触发序列递增,序列的当前值依旧停留在1。
  4. 新增用户时Hibernate从序列取到的第一个值就是1,插入时和已存在的ID冲突,触发报错。
解决方案

可根据业务场景任选一种:

  • 方案一:使用表独立自增序列
    修改Flyway建表语句,给id字段指定自增属性,同时删除多余的语法逗号:
    create table "user"(
      id serial8 not null primary key,
      username varchar(255)
    );
    
    插入测试数据后追加SQL重置该表关联序列的当前值:
    insert into "user" values (1, 'user1');
    insert into "user" values (2, 'user2');
    insert into "user" values (3, 'user3');
    -- 重置序列到当前最大ID
    SELECT setval('user_id_seq', (SELECT MAX(id) FROM "user"));
    
    同时修改主键生成策略为IDENTITY:
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    protected ID id;
    
  • 方案二:继续使用Hibernate全局序列
    不需要修改建表和实体类配置,只需在V1_init.sql脚本末尾追加SQL重置全局序列的当前值:
    SELECT setval('hibernate_sequence', (SELECT MAX(id) FROM "user"));
    
    该方案适合多表共用同一个全局序列生成主键的场景。
  • 方案三:插入测试数据时不指定ID
    修改插入语句,让数据库自动生成ID,会自动推进对应序列的当前值:
    insert into "user" (username) values ('user1');
    insert into "user" (username) values ('user2');
    insert into "user" (username) values ('user3');
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 03:15:02