使用Hibernate嵌入式复合主键后,如何获取自增ID更新值?
解决Hibernate @Embeddable复合主键自增ID不回写问题
问题原因
JPA规范中,复合主键内的自增字段(IDENTITY策略)默认不会自动回填,Hibernate对嵌入式主键的生成值处理逻辑不同于单一主键,再加上自动提交的H2数据库事务特性,导致插入后ID字段始终为null。
解决方案
方案1:调整主键字段的插入属性
修改FormViewPk中的id字段配置,设置insertable = false和updatable = false,让数据库负责生成ID,同时让Hibernate在插入后自动读取该值:
@Embeddable @Data public class FormViewPk implements Serializable { @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id", columnDefinition = "int(10) unsigned NOT NULL AUTO_INCREMENT", insertable = false, updatable = false) private Long id; @Column(name = "curtime", columnDefinition = "int(10) unsigned NOT NULL DEFAULT '0'") private Integer curtime; }
方案2:手动刷新实体获取最新ID
调用saveAndFlush后,通过refresh方法强制从数据库同步最新数据,确保ID被回填:
FormView formView = new FormView(); FormViewPk pk = new FormViewPk(); pk.setCurtime(1620000000); formView.setFormViewPk(pk); // 保存并刷新会话 formView = formViewRepository.saveAndFlush(formView); // 强制从数据库拉取最新实体数据 formViewRepository.refresh(formView); // 此时formView.getFormViewPk().getId()会返回数据库生成的自增值
方案3:使用Hibernate特定注解增强生成逻辑
如果上述方案无效,可添加Hibernate的@Generated注解,显式指定字段在插入后生成值:
@Embeddable @Data public class FormViewPk implements Serializable { @GeneratedValue(strategy = GenerationType.IDENTITY) @Generated(GenerationTime.INSERT) @Column(name = "id", columnDefinition = "int(10) unsigned NOT NULL AUTO_INCREMENT") private Long id; @Column(name = "curtime", columnDefinition = "int(10) unsigned NOT NULL DEFAULT '0'") private Integer curtime; }
注意事项
- 确保
FormViewPk正确实现Serializable接口,且@Data注解生成了基于所有主键字段的equals和hashCode方法(这是复合主键的强制要求)。 - H2数据库开启自动提交时,事务边界会影响实体状态同步,
saveAndFlush+refresh的组合能确保获取到最新的数据库数据。
内容的提问来源于stack exchange,提问作者sergiopf
相关产品推荐
相关产品推荐

