You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot 3迁移至Hibernate 6时,替换自定义ID生成逻辑的正确方案咨询

Spring Boot 3迁移至Hibernate 6时,替换自定义ID生成逻辑的正确方案咨询

嘿,我刚好研究过Hibernate 6的ID生成器变化,你的问题很典型——Spring Boot3升级后,原来继承IdentityGenerator的自定义生成器确实失效了,咱们来一步步搞定它:

首先得搞清楚为啥原来的代码用不了:Hibernate 6彻底重构了ID生成器的体系,原来的IdentityGenerator不再是可以直接继承重写generate方法的类,而且新的IdentifierGenerator是个接口,根本没有super.generate()这种方法可以调用。

要实现「如果ID已存在就用,不存在则自动生成」的逻辑,正确的做法是自定义生成器内部委托Hibernate内置的Identity生成器,具体代码如下:

import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.id.IdentifierGenerator;
import org.hibernate.id.IdentityGenerator;
import org.hibernate.id.factory.spi.GeneratorCreationContext;
import org.hibernate.type.Type;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.PropertyAccessorFactory;

import java.util.Properties;

public class UseIdOrGenerate implements IdentifierGenerator {

    // 内置的Identity生成器,用来处理需要自动生成ID的场景
    private IdentifierGenerator delegateGenerator;

    @Override
    public void initialize(Type type, Properties properties, GeneratorCreationContext context) {
        // 初始化委托生成器,复用Hibernate原生的Identity生成逻辑
        this.delegateGenerator = new IdentityGenerator();
        this.delegateGenerator.initialize(type, properties, context);
    }

    @Override
    public Object generate(SharedSessionContractImplementor session, Object entity) {
        BeanWrapper beanWrapper = PropertyAccessorFactory.forBeanPropertyAccess(entity);
        Object currentId = beanWrapper.getPropertyValue("id");

        // 如果已有ID,直接返回;否则调用委托生成器生成新ID
        if (currentId != null) {
            return currentId;
        } else {
            return delegateGenerator.generate(session, entity);
        }
    }
}

接下来在实体类里配置这个生成器就行,注意注解的写法要适配Spring Boot3(用jakarta.persistence替代旧的javax.persistence):

import jakarta.persistence.*;

@Entity
public class YourEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY, generator = "useIdOrGenerate")
    @GenericGenerator(name = "useIdOrGenerate", type = UseIdOrGenerate.class)
    private Long id;

    // 其他字段和方法...
}

另外给你提个小建议:如果你的需求只是个别实体需要这种逻辑,其实也可以不用自定义生成器——直接给ID字段加上@GeneratedValue(strategy = GenerationType.IDENTITY),然后在保存前手动判断ID是否为空,为空则让Hibernate自动生成,不为空就用传入的ID,这种方式更轻量。

备注:内容来源于stack exchange,提问作者Isvoran Andrei

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 10:14:50