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
相关产品推荐
相关产品推荐

