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

JPA持久化后嵌入式ID的自动生成字段idMaterialResource为null

问题分析与解决方案

核心问题

你遇到的两个关键问题:

  1. 数据库脚本的主键字段名与实体类映射不匹配,导致JPA无法正确识别主键
  2. 嵌入式复合主键中自动生成的ID字段,默认不会被JPA自动回填到实体对象中

步骤1:修正数据库脚本

你的Flyway脚本中主键字段名错误,与实体类的列名不对应,这会导致JPA映射异常。修正后的SQL如下:

CREATE TABLE IF NOT EXISTS material_resource(
    id_materialresource INT NOT NULL AUTO_INCREMENT,
    id_company INT NOT NULL,
    name VARCHAR(255) NOT NULL DEFAULT "",
    identifier VARCHAR(255) NOT NULL DEFAULT "",
    fromDate DATE NOT NULL,
    toDate DATE NOT NULL,
    -- 修正主键字段,与实体类列名保持一致
    PRIMARY KEY (id_materialresource, id_company)
);

步骤2:解决ID回填问题

针对嵌入式ID的IDENTITY生成字段,有三种可行方案:

方案A:手动刷新实体(快速解决)

在persist操作后,调用EntityManager的refresh方法,强制从数据库同步最新的实体状态,生成的ID会被回填:

MaterialResourceId id = new MaterialResourceId(null, 1);
MaterialResource materialResource = new MaterialResource(id, "Material resource name", ...);
EntityManager em = getEntityManager();
em.persist(materialResource);
// 刷新实体获取生成的ID
em.refresh(materialResource);
// 此时materialResource.getMaterialResourceId().getIdMaterialResource()已赋值

方案B:调整JPA配置(优雅解决)

确保Hibernate启用新的生成器映射(Spring Boot默认已开启),并确认嵌入式ID的注解配置正确:

  1. 如果是Spring Boot,在application.properties中添加(默认已开启,可省略):
spring.jpa.hibernate.id.new_generator_mappings=true
  1. 保持现有嵌入式ID结构,确保@GeneratedValue和@Column注解配置正确:
@Embeddable
@Data
@AllArgsConstructor
@NoArgsConstructor
public class MaterialResourceId implements Serializable {
    private static final long serialVersionUID = 1L;

    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id_materialresource", nullable = false)
    private Integer idMaterialResource;

    @Column(name = "id_company", nullable = false)
    private Integer idCompany;
}

方案C:改用@IdClass替代@EmbeddedId(可选)

如果觉得嵌入式ID配置繁琐,可以切换为@IdClass实现复合主键,这种方式下ID会自动回填:

  1. 主键类保持不变(无需@Embeddable注解):
@Data
@AllArgsConstructor
@NoArgsConstructor
public class MaterialResourceId implements Serializable {
    private static final long serialVersionUID = 1L;
    private Integer idMaterialResource;
    private Integer idCompany;
}
  1. 修改实体类:
@Entity
@Table(name = "material_resource")
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@IdClass(MaterialResourceId.class)
public class MaterialResource {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id_materialresource")
    private Integer idMaterialResource;

    @Id
    @Column(name = "id_company")
    private Integer idCompany;

    @Column(name = "name", nullable = false)
    private String name = "";
    ...
}

内容的提问来源于stack exchange,提问作者Jesús Moncada Ramírez

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 09:29:52