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

Spring Boot是否通过@GeneratedValue改变ID自增方式?版本差异咨询

解决Spring Boot 2.0.0中Hibernate实体共享主键序列的问题

你遇到的这个情况我之前帮不少开发者排查过,确实是Spring Boot 2.0.0对Hibernate自动配置做的一处关键变更导致的。在1.5.10版本里,Hibernate默认会给每个JPA实体单独维护自增主键序列,所以Car和Airplane的主键都能从1开始,互相不干扰;但升级到2.0.0之后,默认逻辑变成了所有实体共享一个全局序列,就出现了你描述的Car ID是1,Airplane ID会接着用后续数字的情况。

问题根源

Spring Boot 2.0.0把Hibernate的hibernate.id.new_generator_mappings参数默认值从false改成了true。这个参数控制Hibernate是否启用JPA 2.1规范的新生成器映射:

  • 当值为false(1.5.x版本默认):Hibernate使用旧版生成器逻辑,每个实体都会单独创建自己的序列/表生成器,主键自增完全独立。
  • 当值为true(2.0.0版本默认):Hibernate默认使用SequenceStyleGenerator,如果实体没有显式指定生成器,就会共用一个名为hibernate_sequence的全局序列(适用于PostgreSQL等支持序列的数据库);对于MySQL这类不支持序列的数据库,则会用一个全局的表生成器,自然就导致了主键序列共享。

三种解决方案

1. 快速回退到旧版生成器逻辑

如果你不想折腾,只想快速恢复1.5.x的行为,直接在配置文件里把参数改回去就行:

# application.properties
spring.jpa.properties.hibernate.id.new_generator_mappings=false

这种方式简单直接,但缺点是会错过JPA 2.1的一些新特性。

2. 为每个实体显式指定独立生成器(推荐)

如果想保留JPA 2.1的新特性,同时保证实体主键独立,最稳妥的方式是给每个实体单独定义生成器:

针对支持序列的数据库(如PostgreSQL):
Car实体:

@Entity
@SequenceGenerator(
    name = "car_seq",
    sequenceName = "car_sequence",
    initialValue = 1,
    allocationSize = 1
)
public class Car {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "car_seq")
    private Long id;
    // 其他字段、构造方法和Getter/Setter
}

Airplane实体:

@Entity
@SequenceGenerator(
    name = "airplane_seq",
    sequenceName = "airplane_sequence",
    initialValue = 1,
    allocationSize = 1
)
public class Airplane {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "airplane_seq")
    private Long id;
    // 其他字段、构造方法和Getter/Setter
}

针对MySQL这类不支持序列的数据库:
改用TableGenerator,给每个实体分配独立的生成器表:

@Entity
@TableGenerator(
    name = "car_table_gen",
    table = "car_id_generator",
    pkColumnName = "seq_name",
    valueColumnName = "seq_value",
    pkColumnValue = "car_seq",
    initialValue = 1,
    allocationSize = 1
)
public class Car {
    @Id
    @GeneratedValue(strategy = GenerationType.TABLE, generator = "car_table_gen")
    private Long id;
    // ...
}

Airplane实体同理,只需要把生成器名称、表名等改成对应的即可。

3. 自定义全局生成器策略(进阶)

如果你有大量实体,不想逐个配置,可以自定义Hibernate的生成器逻辑,让它默认给每个实体创建独立序列。这需要扩展SequenceStyleGenerator或者编写自定义IdentifierGenerator,实现起来稍复杂,适合有Hibernate底层经验的开发者。

验证方式

配置完成后启动应用,依次创建Car和Airplane实例,检查它们的主键是否都从1开始,确认序列不再共享即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 09:11:53