Hibernate版本升级后@TableGenerator表创建及ID重复问题咨询
Hibernate 版本升级后@TableGenerator ID冲突问题分析与解决
为什么会出现这个问题?
- 在Hibernate 5.0.3.Final里,
@TableGenerator的实现比较宽松:当配置的itpGenerator表不存在时,它不会严格创建表,而是默认使用内存计数器或者复用PostgreSQL表自带的隐式自增序列生成ID。所以你看不到生成器表,但ID能从1001开始正常递增——只是生成器的状态没有持久化到数据库里。 - 升级到5.4.24.Final后,Hibernate严格遵循JPA规范执行:它会自动创建
@TableGenerator指定的生成器表,并且按照注解配置的initialValue=1000初始化表中的起始值。之前的数据ID已经超过1001,新生成器又从1001开始分配ID,自然和现有数据的主键冲突,触发唯一约束错误。
解决办法
1. 手动修正生成器表的起始值
直接在PostgreSQL中执行SQL,将itpGenerator表的next_val更新到现有数据的最大ID+分配大小的数值,确保后续分配的ID段不冲突:
-- 替换成你的生成器名称和实体表名 UPDATE itpGenerator SET next_val = (SELECT MAX(id) FROM 你的实体表名) + 100 WHERE generator_name = '你的@TableGenerator配置的name属性值';
2. 禁止Hibernate自动创建表
如果不需要Hibernate自动维护表结构,修改配置禁用自动建表逻辑:
- XML配置(hibernate.cfg.xml):
<property name="hibernate.hbm2ddl.auto">none</property>
- Spring Boot配置(application.properties):
spring.jpa.hibernate.ddl-auto=none
注意:这么做的前提是你已经手动创建了
itpGenerator表,并且将next_val设为正确的起始值。
3. 临时调整@TableGenerator的初始值
先把父类中@TableGenerator的initialValue改成现有数据的最大ID+1,启动项目一次,让Hibernate自动更新生成器表的next_val,之后可以再把initialValue改回原来的配置(也可以保留,生成器后续会自动递增)。
4. 切换为PostgreSQL原生序列(推荐)
表生成器本身适配PostgreSQL的特性较差,换成原生序列更稳定:
@Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "entity_seq") @SequenceGenerator(name = "entity_seq", sequenceName = "entity_seq", initialValue = 1001, allocationSize = 100) private Long id;
这种方式下Hibernate会直接调用数据库的序列,不会再出现版本升级导致的表创建和ID重置问题。
内容的提问来源于stack exchange,提问作者Tal Levi
相关产品推荐
相关产品推荐

