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

使用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 20:50:33