Hibernate 6的自定义ID生成器:使用现有ID,或回退到自增

后端开发 2026-07-08

我正在将我的应用升级到 Java 21Spring Boot 3.5.x,这带来了Hibernate 6作为依赖。作为升级的一部分,我现有的自定义ID生成器坏了,需要重写以兼容Hibernate 6。

  • 如果实体已经设置了ID → 使用它
  • 如果ID为 null → 让数据库自动生成一个(像 IDENTITY / AUTO_INCREMENT)
public class UseExistingOrGenerateIdGenerator extends IdentityGenerator 
                                               implements IdentifierGenerator {
    @Override
    public Serializable generate(SharedSessionContractImplementor session, 
                                 Object object) throws HibernateException {
        Serializable id = session.getEntityPersister(null, object)
                .getClassMetadata().getIdentifier(object, session);
        return id != null ? id : super.generate(session, object);
    }
}

我需要的:

一个与Hibernate 6等价的实现,能够:

  1. 从实体读取当前ID
  2. 如果不为null → 使用它
  3. 如果为null → 将其委托给 数据库 AUTO_INCREMENT(不是Hibernate管理的序列)

环境:

  • Hibernate 6.x
  • Spring Boot 3.5.14
  • MySQL,使用 AUTO_INCREMENT

为什么不能把 SequenceStyleGenerator 作为回退:

我的表已有非连续的ID的现有数据。例如:

users table:       max id 300
products table:    max id 50 000
orders table:      max id 120 000

如果我使用共享序列,它会让所有表从 120 000+ 开始,这不对。每个表都需要自己的 AUTO_INCREMENT,才能自然地从自身的最大ID继续。

解决方案

如果我使用共享序列,它会让所有表从 120 000+ 开始

不,这并不错误。这是实际的解决方案。表里已经有一些记录,因此你的自增需要从超过你已使用的值开始。假设某张表里有一个值是2 的记录。现在,如果这个ID变成 auto_increment,你会期望得到的值是什么?如果是1,那么第二次插入就会失败。所以它需要大于2。若你也有一个4 的值呢?3对于 auto_increment 来说会是一个有效值吗?当然不是。因为在这种情况下,插入3 之后,下一次插入会尝试4,再次失败。

因此,你要么接受 auto_increment 会从你上一个值+ 1开始,要么,如果你真的非常想重构,那么你可以重构你的数据库,将ID收缩,使它们之间不再有间隙。然而,这样的重构很可能会非常困难,尤其是当系统已经依赖这些ID的取值(如外键、应用层常量、导出等)时,而且坦白说,除非你为即将自增的新插入值赋予某种特殊意义,否则没有必要这样做。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章