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

Spring Boot实体类含复合主键时如何正确生成自增ID?

问题根因

JPA官方规范本身不支持在@IdClass定义的复合主键字段上使用@GeneratedValue自动生成值,只有当实体类使用单一主键时,@GeneratedValue才会被框架正常识别处理,这是你当前功能异常的核心原因。
另外你需要确保你的TmTrxFlowSerializable类已经正确实现Serializable接口,且重写了equals、hashCode方法,字段名、类型和实体类中的主键字段完全一致,否则也会引发主键相关异常

可用解决方案
  • 方案1:改用@EmbeddedId注解定义复合主键,配合Hibernate扩展能力实现字段自动生成
    首先定义可嵌入的主键类:

    @Embeddable
    public class TmTrxFlowId implements Serializable {
        private Integer tmTrxProcedureId;
        @SequenceGenerator(name = "some_seq", sequenceName = "empid_seq")
        @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "some_seq")
        private Integer tmTrxFlowId;
        // 必须补充无参构造、全参构造、equals、hashCode方法
    }
    

    然后修改实体类:

    @Entity
    @DynamicUpdate
    @DynamicInsert
    @Table(name = "tm_trx_flow")
    public class TmTrxFlow {
        @EmbeddedId
        private TmTrxFlowId id;
        // 其他业务字段、getter、setter省略
    }
    

    注意该方案依赖Hibernate的扩展能力,标准JPA仍不支持嵌入主键内的字段自动生成,需要确保你使用的ORM框架为Hibernate。

  • 方案2:手动实现序列值赋值逻辑,兼容标准JPA规范
    去掉主键字段上的@GeneratedValue注解,在保存实体前手动调用序列查询获取值,赋值给对应主键字段后再执行保存:

    // 示例代码,根据你使用的数据库类型调整序列查询语句
    Integer flowId = jdbcTemplate.queryForObject("select empid_seq.nextval from dual", Integer.class);
    tmTrxFlow.setTmTrxFlowId(flowId);
    // 再执行保存操作
    tmTrxFlowRepository.save(tmTrxFlow);
    

    该方案完全符合JPA规范,兼容性最好,不会依赖ORM框架的私有扩展。

  • 方案3:调整表结构设计,新增单一自增主键作为表唯一主键,将原来的两个主键字段改为普通唯一索引约束,这样可以直接使用@GeneratedValue,是最符合JPA设计规范的实现方式。

内容的提问来源于stack exchange,提问作者Adam Abdullah

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 15:15:03