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

非ID列用@GeneratedValue生成值始终为null,自定义生成器未触发

非ID列自定义序列生成器未触发问题排查与解决

问题情况

尝试为实体的非ID列ss_request_number生成REQ00000001格式的自增序列号,使用@GeneratedValue配合自定义ReqSequenceGenerator实现,但该字段值始终为null,自定义生成器完全未被调用。当前使用H2数据库,疑惑是否需要为该列设置特定约束。

问题原因

  1. Hibernate默认行为限制:@GeneratedValue注解默认仅对@Id标记的主键列生效,非ID列不会自动触发生成逻辑。
  2. 数据库类型冲突:实体类中@Column的columnDefinition = "serial"配置,会让H2数据库自动为该列生成数值型自增值,覆盖了自定义生成器的执行逻辑。
  3. 缺少生成标记:未添加@Generated注解告知Hibernate该字段值由框架生成,而非应用程序手动赋值。

解决方案

  1. 移除冲突的数据库类型配置:删除@Column中的columnDefinition = "serial",避免数据库自动生成逻辑干扰自定义生成器。
  2. 添加生成时机注解:为非ID列添加@Generated(GenerationTime.INSERT),标记该字段在插入数据时由Hibernate自动生成。
  3. 确保序列配置正确:可手动在Liquibase中创建对应序列(可选,Hibernate也会自动创建),保证自定义生成器能获取到自增序列值。

修正后代码示例

实体类代码

import org.hibernate.annotations.Parameter;
import org.hibernate.annotations.*;
import javax.persistence.*;
import java.util.UUID;

@Data
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "ss_request", schema = "AGENCY_SS_APP")
public class SSRequest {

    private static final long serialVersionUID = 1L;

    // ID列,生成正常
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Schema(description = "ss_requestid")
    @Column(name = "ss_request_id", nullable = false, updatable = false, length = 36)
    @Type(type = "uuid-char")
    private UUID ssRequestId;

    // 修正后的自增序列列
    @Column(name="ss_request_number", updatable = false, nullable = false, length = 20)
    @Schema(description ="Request Number")
    @Generated(GenerationTime.INSERT) // 标记插入时生成字段值
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "request_seq")
    @GenericGenerator(
            name = "request_seq",
            strategy = "com.vermontmutual.agencyssportal.util.ReqSequenceGenerator",
            parameters = {
                    @Parameter(name = ReqSequenceGenerator.INCREMENT_PARAM, value = "1"),
                    @Parameter(name = ReqSequenceGenerator.VALUE_PREFIX_PARAMETER, value = "REQ"),
                    @Parameter(name = ReqSequenceGenerator.NUMBER_FORMAT_PARAMETER, value = "%08d") })
    private String ssRequestNumber; 
}

Liquibase配置

<!-- 可选:手动创建序列,确保与生成器配置一致 -->
<createSequence sequenceName="request_seq" startValue="1" incrementBy="1" schemaName="AGENCY_SS_APP"/>

<column name="ss_request_number" type="VARCHAR(20)">
    <constraints nullable="false" />
</column>

自定义生成器代码(无需修改)

package com.vermontmutual.agencyssportal.util;

import org.hibernate.HibernateException;
import org.hibernate.MappingException;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.id.enhanced.SequenceStyleGenerator;
import org.hibernate.internal.util.config.ConfigurationHelper;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.type.LongType;
import org.hibernate.type.Type;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.Serializable;
import java.util.Properties;

public class ReqSequenceGenerator extends SequenceStyleGenerator {

    Logger LOG = LoggerFactory.getLogger(ReqSequenceGenerator.class);

    public static final String VALUE_PREFIX_PARAMETER = "valuePrefix";
    public static final String VALUE_PREFIX_DEFAULT = "";
    private String valuePrefix;

    public static final String NUMBER_FORMAT_PARAMETER = "numberFormat";
    public static final String NUMBER_FORMAT_DEFAULT = "%d";
    private String numberFormat;


    @Override
    public Serializable generate(SharedSessionContractImplementor session, Object object) throws HibernateException {
        LOG.info("Inside generate of Request Number:");
        return valuePrefix + String.format(numberFormat, super.generate(session, object));
    }

    @Override
    public void configure(Type type, Properties params, ServiceRegistry serviceRegistry) throws MappingException {
        LOG.info("Inside configure of Request Number:");
        super.configure(LongType.INSTANCE, params, serviceRegistry);
        valuePrefix = ConfigurationHelper.getString(VALUE_PREFIX_PARAMETER, params, VALUE_PREFIX_DEFAULT);
        numberFormat = ConfigurationHelper.getString(NUMBER_FORMAT_PARAMETER, params, NUMBER_FORMAT_DEFAULT);
    }

}

内容的提问来源于stack exchange,提问作者Sharvari Nagesh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 01:57:38