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

JPA关联类自动获取Product生成ID的实现方案咨询

问题:保存Product实体时自动为关联实体赋值productId

现有如下Product实体类,其id通过@GeneratedValue实现数据库自动递增:

@Data
@Entity
@Table(name = "products", schema = "laboratory", catalog = "laboratory")
@JsonIgnoreProperties({ "hibernateLazyInitializer", "handler" })
public class Product {
    @Id
    @GeneratedValue
    private int id;
    @ManyToOne(fetch = FetchType.LAZY, cascade= CascadeType.ALL)
    @JoinColumn(name = "project_id")
    @Transient
    private Project project; // 只读字段
    @Column(name="project_id") // 存储关联项目的id到数据库
    private int projectId;

    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name="id")
    private Inspection inspection;
    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name="id")
    private Information information;
    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name="id")
    private Departure departure;
    private String un;
    private String tc;
}

Product需要关联Inspection、Information、Departure三个实体,以Information为例,其结构如下:

@Data
@Entity
@Table(name = "products_informations", schema = "laboratory", catalog = "laboratory")
@JsonIgnoreProperties({ "hibernateLazyInitializer", "handler" })
public class Information {
    @Id
    private int productId;
    private String description;
    private String model;
    private int year;
    private String serialNumber;
    private int odometre;
    private int noCrochet;
    private int nbKeys;
    private String localisation;
    private String cemeteryPosition;
    @JsonFormat(pattern = "yyyy-MM-dd")
    private Date receptionDate;
}

需求:调用save()方法保存Product时,三个关联实体的productId能自动获取Product生成的id,无需在控制器手动赋值。


解决方案

1. 修正关联映射逻辑

原代码中Product类的@OneToOne注解配置错误,@JoinColumn(name="id")会导致关联实体使用自身的id字段关联,不符合需求。需要通过双向关联+@MapsId注解实现主键自动同步。

2. 修改Product类的关联注解

将Product中三个@OneToOne关联改为mappedBy形式,指向关联实体中关联Product的属性名:

@Data
@Entity
@Table(name = "products", schema = "laboratory", catalog = "laboratory")
@JsonIgnoreProperties({ "hibernateLazyInitializer", "handler" })
public class Product {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY) // 明确指定自增策略,避免依赖默认配置
    private int id;
    
    @ManyToOne(fetch = FetchType.LAZY, cascade= CascadeType.ALL)
    @JoinColumn(name = "project_id")
    @Transient
    private Project project;
    
    @Column(name="project_id")
    private int projectId;

    // 改为mappedBy,指向关联实体中的product属性
    @OneToOne(mappedBy = "product", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private Inspection inspection;
    
    @OneToOne(mappedBy = "product", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private Information information;
    
    @OneToOne(mappedBy = "product", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private Departure departure;
    
    private String un;
    private String tc;
}

3. 修改关联实体(以Information为例)

给关联实体的@Id字段添加@MapsId注解,并添加双向关联的Product属性:

@Data
@Entity
@Table(name = "products_informations", schema = "laboratory", catalog = "laboratory")
@JsonIgnoreProperties({ "hibernateLazyInitializer", "handler" })
public class Information {
    @Id
    @MapsId // 该注解会让Hibernate将关联Product的id赋值给当前实体的主键productId
    private int productId;
    
    // 双向关联Product,指定外键为product_id(即当前实体的主键)
    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "product_id")
    private Product product;
    
    private String description;
    private String model;
    private int year;
    private String serialNumber;
    private int odometre;
    private int noCrochet;
    private int nbKeys;
    private String localisation;
    private String cemeteryPosition;
    @JsonFormat(pattern = "yyyy-MM-dd")
    private Date receptionDate;
}

Inspection和Departure类做完全相同的修改即可。

4. 保存逻辑示例

保存时只需构建Product及关联实体的关系,无需手动赋值productId:

// 构建关联实体
Information info = new Information();
info.setDescription("测试描述");
// 其他属性赋值...

// 构建Product并关联
Product product = new Product();
product.setInformation(info);
info.setProduct(product); // 建立双向关联

// 保存Product,Hibernate会自动处理id同步
productRepository.save(product);

原理说明

  • @MapsId注解会让Hibernate将关联实体(Product)的主键值,赋值给当前实体的主键(productId)。
  • CascadeType.ALL配置会让save()操作级联到关联实体,Hibernate会先保存Product生成自增id,再自动将该id赋值给关联实体的productId,最后保存关联实体。

内容的提问来源于stack exchange,提问作者Charlo Poitras

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 22:27:33