Hibernate GenerationType.IDENTITY重启后ID跳增20问题求助
问题分析与解决方案
问题根源
你使用的GenerationType.IDENTITY在部分数据库(比如PostgreSQL)底层是基于序列实现的,Hibernate默认会预缓存20个序列值做性能优化——重启应用后,未使用的缓存值会直接丢弃,导致ID跳转到下一个缓存段(比如首次用了1-3,剩下17个没用到,重启后就从21开始)。你尝试的spring.jpa.properties.hibernate.id.new_generator_mappings=false是针对旧版生成器的配置,对IDENTITY模式下的序列缓存无效。
具体解决方案
针对PostgreSQL(IDENTITY底层依赖序列)
方式1:全局修改序列缓存大小
在application.properties或application.yml中添加配置,强制所有序列每次只预取1个ID:
spring.jpa.properties.hibernate.id.optimizer.pooled.preferred_pool_size=1
方式2:实体类显式指定序列规则
直接替换IDENTITY为SEQUENCE生成策略,手动设置增量步长为1:
@Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "your_entity_seq") @SequenceGenerator( name = "your_entity_seq", sequenceName = "your_entity_id_seq", initialValue = 1, allocationSize = 1 ) @Column(unique = true, nullable = false) private Long id;
针对MySQL(依赖auto_increment)
MySQL的auto_increment默认不会出现固定跳20的情况,若确实存在问题,按以下步骤排查:
- 检查自增配置是否正常:
SHOW VARIABLES LIKE 'auto_increment%';
确保auto_increment_increment和auto_increment_offset的值都是1。
2. 若配置异常,执行以下SQL修改(需重启MySQL永久生效):
SET GLOBAL auto_increment_increment=1; SET GLOBAL auto_increment_offset=1;
同时在MySQL配置文件(my.cnf/my.ini)中添加:
auto_increment_increment = 1 auto_increment_offset = 1
通用禁用预缓存方案
如果不想修改实体注解,可通过全局配置关闭Hibernate的序列预缓存:
spring.jpa.properties.hibernate.id.optimizer.pooled.loose=false spring.jpa.properties.hibernate.id.optimizer.pooled.preferred_pool_size=1
注意事项
- 设置增量步长为1会牺牲部分插入性能(每次插入都要去数据库获取序列值),高并发场景下不建议强制追求连续ID。
- 生产环境中,ID跳号是常见的性能优化手段,除非业务强依赖连续ID,否则无需修改。
内容的提问来源于stack exchange,提问作者Ranjithkumar
相关产品推荐
相关产品推荐

