Hibernate 6的自定义ID生成器:使用现有ID,或回退到自增
我正在将我的应用升级到 Java 21 和 Spring 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等价的实现,能够:
- 从实体读取当前ID
- 如果不为null → 使用它
- 如果为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导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。