Hibernate 6自定义ID生成器:使用已有ID或回退至自增
Hibernate 6 兼容的自定义ID生成器实现
需求背景
升级至Java 21和Spring Boot 3.5.x(引入Hibernate 6)后,原有自定义ID生成器无法正常工作,需要重写以满足以下要求:
- 若实体已设置ID,直接使用该ID
- 若ID为null,则由数据库的AUTO_INCREMENT(IDENTITY)机制自动生成
原有Hibernate旧版本实现
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 等效实现
Hibernate 6中ClassMetadata已被废弃,需改用EntityPersister的新API来获取实体ID,同时确保回退逻辑直接委托数据库的自增机制,而非Hibernate管理的序列。以下是兼容实现:
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.id.IdentityGenerator; import org.hibernate.id.IdentifierGenerator; import org.hibernate.persister.entity.EntityPersister; public class UseExistingOrGenerateIdGenerator extends IdentityGenerator implements IdentifierGenerator { @Override public Object generate(SharedSessionContractImplementor session, Object entity) { // 获取当前实体的EntityPersister EntityPersister persister = session.getEntityPersister(null, entity); // 获取实体当前的ID值 Object id = persister.getIdentifier(entity, session); // 如果ID不为null,直接返回;否则调用父类逻辑(触发数据库AUTO_INCREMENT) return id != null ? id : super.generate(session, entity); } }
关键说明
- 获取实体ID:通过
EntityPersister.getIdentifier(entity, session)替代旧版的ClassMetadataAPI,这是Hibernate 6推荐的方式 - 回退逻辑:父类
IdentityGenerator的generate方法会直接触发数据库的IDENTITY/AUTO_INCREMENT机制,确保每个表使用自身的自增序列,不会出现跨表ID延续的问题
为什么不能使用SequenceStyleGenerator
现有业务表的ID不连续,各表最大ID差异较大:
users table: max id 300 products table: max id 50000 orders table: max id 120000
若使用SequenceStyleGenerator的共享序列,所有新插入的记录会从最大的ID值(120000+)开始,不符合业务要求。而上述实现依赖数据库原生的AUTO_INCREMENT,每个表会从自身的最大ID自然延续自增。
内容的提问来源于stack exchange,提问作者visal vishmitha
相关产品推荐
相关产品推荐

