Hibernate 6适配:自定义IdentifierGenerator如何委托默认生成器处理空ID
适配Hibernate 6的自定义ID生成器实现
Hibernate 6对IdentifierGenerator接口做了重大调整,包括方法签名变更、API废弃等,以下是针对你的需求的适配方案:
1. 调整自定义ID生成器代码
Hibernate 6中IdentifierGenerator的generate方法签名改为接收IdentifierGeneratorContext参数,且原代码中super.generate的调用逻辑本身存在问题(因为IdentifierGenerator是接口,无父类实现)。我们通过组合默认生成器的方式实现需求:
@Slf4j public class CustomIdGenerator implements IdentifierGenerator { private final IdentifierGenerator defaultGenerator; // Hibernate会自动注入指定的默认生成器 public CustomIdGenerator(IdentifierGenerator defaultGenerator) { this.defaultGenerator = defaultGenerator; } @Override public Object generate(IdentifierGeneratorContext context) { Object entity = context.getOwner(); // 获取实体当前的ID(替代废弃的getClassMetadata方法) EntityPersister persister = context.getSession().getEntityPersister(null, entity); Object id = persister.getIdentifierAccessor().getIdentifier(entity); // 判断ID是否有效:非空且为正整数 if (id instanceof Long longId && longId > 0) { log.debug("使用提供的ID [{}] 用于实体 [{}]", id, entity.getClass().getName()); return id; } // ID无效或未设置,交由默认生成器生成 log.debug("ID未设置或无效,Hibernate将为实体 [{}] 生成新ID", entity.getClass().getName()); return defaultGenerator.generate(context); } }
2. 调整实体类的注解配置
Hibernate 6中@GeneratedValue与@GenericGenerator的配合方式略有调整,需要明确指定默认生成器类型(沿用你原来的IDENTITY策略):
@Entity public class Tournament { @Id @GenericGenerator( name = "customIdGenerator", type = CustomIdGenerator.class, // 指定默认生成器为IDENTITY类型 parameters = @Parameter(name = "defaultGenerator", value = "identity") ) @GeneratedValue(generator = "customIdGenerator") private Long id; // 其他字段、构造方法及Getter/Setter }
关键变更说明
- 废弃API替换:用
EntityPersister.getIdentifierAccessor().getIdentifier(entity)替代原代码中废弃的getClassMetadata().getIdentifier方法 - 方法签名适配:
generate方法现在接收IdentifierGeneratorContext,通过该上下文获取实体实例、会话等信息 - 生成器组合:通过构造器注入默认生成器,避免原代码中错误的
super.generate调用,逻辑更清晰
内容的提问来源于stack exchange,提问作者L Jones
相关产品推荐
相关产品推荐

