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

Hibernate SequenceGenerator插入超50条数据时出现ID重复异常

问题根本原因

你遇到的ID冲突问题是JPA序列生成器的allocationSize配置和数据库序列的步长配置不匹配导致的:

  • JPA的@SequenceGenerator注解默认allocationSize值为50,该参数的作用是:JPA每次从数据库查询一次序列当前值后,会在应用内存中连续分配allocationSize个ID,用完才会再次查询数据库序列。
  • 你在Liquibase中配置的数据库序列步长incrementBy="10",每次查询序列时只会比上次返回的值大10。
    这就导致JPA以为自己拿到的起始值之后的50个ID都是独占可用的,但实际上数据库序列10个之后就会进入下一轮分配,第二次查询到的序列值会和之前JPA已经分配过的ID重复,就触发了主键冲突异常。

你观察到的几个现象完全符合这个逻辑:

  • 应用生成ID每次自增1:这是JPA在内存中批量分配ID的正常表现,不需要每次生成ID都查询数据库
  • 数据库手动查序列步长为10:和你Liquibase配置一致
  • 固定保存第50个对象时报错:刚好是第一批分配的50个ID用完,JPA第二次查询数据库拿到的序列值已经被之前的分配覆盖,出现重复ID。插入数量少于50时第一批ID没用完,不会触发二次查询,因此不会报错。
解决方案

两边的步长配置对齐即可,有两种可选方案:

方案1:保持数据库序列配置不变,修改JPA注解

显式给@SequenceGenerator指定allocationSize = 10,和数据库步长一致:

public class Publication implements Serializable, Identifiable {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
    @SequenceGenerator(name = "sequenceGenerator", allocationSize = 10)
    private Long id;
}

方案2:保持JPA默认配置不变,修改数据库序列步长

把Liquibase中序列的incrementBy改成和JPA默认allocationSize一致的50:

<createSequence incrementBy="50" sequenceName="sequence_generator" startValue="1" cacheSize="10"/>

注意:修改配置前请先确认当前数据库序列的当前值,避免修改后生成的ID和已存在的业务数据主键冲突,生产环境操作前建议先备份数据。

内容的提问来源于stack exchange,提问作者Giacomo Voß

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 18:06:03