首页 > 解决方案 > 使用 orphanRemoval Spring JPA 自动删除子实体

问题描述

目前,我有以下 2 个具有一对多关系的实体 -

@Data
@Entity
@Table(name = "invoice_line")
@IdClass(InvoiceLinePK.class)
public class InvoiceLineEntity {

  @Id
  @Column(name = "line_id")
  private String lineId;

  @Id
  @Column(name = "client_id")
  private Integer clientId;

  @Id
  @Column(name = "invoice_id")
  private String invoiceId;

  @Column(name = "item_id")
  private String itemId;

  @Column(name = "amount")
  private BigDecimal amount;

  @ManyToOne
  private InvoiceEntity invoice;

}
@Entity
@Table(name = "invoice")
@IdClass(InvoicePK.class)
@Data
public class InvoiceEntity {

  @Id
  @Column(name = "client_id")
  private Integer clientId;

  @Id
  @Column(name = "invoice_id")
  private String invoiceId;

  @Column(name = "description")
  private String description;

  @Column(name = "txn_total_amount")
  private BigDecimal txnTotalAmount;

  @Column(name = "created_time", updatable = false)
  @CreationTimestamp
  private Date createdTime;

  @Column(name = "updated_time")
  @UpdateTimestamp
  private Date updatedTime;

  @OneToMany(fetch = FetchType.EAGER, orphanRemoval = true, mappedBy = "invoice")
  private List<InvoiceLineEntity> invoiceLines;

}

在这种情况下,假设我的一张现有发票有 3 行,我收到一个请求,要求此特定发票已更新,现在它只有 1 行而不是之前的 3 行(因此必须删除其他 2 行),我想用这个 1 InvoiceLineEntity 创建一个新的 Invoice 对象,然后做一个invoiceRepository.save(invoice)

我预计其他 2 个 InvoiceLine 记录将被自动删除,因为该orphanRemoval标志已启用。

有人可以告诉我如何通过调整上述两个实体的实体关系结构来实现这种关系吗?

标签: javaspring-boothibernatespring-data-jpa

解决方案


您的子实体必须是关系的所有者,以便允许删除孤儿

如果您更改并添加mappedBy到该关系

  @OneToMany(fetch = FetchType.EAGER, orphanRemoval = true, mappedBy = "bill")
  private List<BillLine> billLines;

那么 BillLine 也必须持有一个引用

public class BillLine {

  @Id
  @Column(name = "line_id")
  private String lineId;

  @Id
  @Column(name = "company_id")
  private Integer companyId;

  @Id
  @Column(name = "bill_id")
  private String billId;

  @Column(name = "item_id")
  private String itemId;

  @Column(name = "amount")
  private BigDecimal amount;

  @ManyToOne
  private Bill bill;

}

现在它将删除孤儿

另外,因为您@Id在每个实体上都有多个。您是否知道必须声明复合类或可嵌入类?如果没有其中一个,则多个 ID 无效。

编辑:

1)我的 bad mappedBy 应该放在里面@OneToMany而不是@JoinColumn. 我已经在我的回答中更正了

2)删除@JoinColumn。你的配置有问题。默认情况下,在保存对主表的引用@OneToMany的一侧插入一列。@ManyToOne您可以覆盖这些默认配置并为映射创建一个单独的表,但是您需要@JoinTable并且我在这里看不到任何原因。

这里

 @JoinColumns(value = { @JoinColumn(name = "company_id", referencedColumnName = "company_id"),
          @JoinColumn(name = "bill_id", referencedColumnName = "bill_id") })

绝对不属于@OneToMany

以下内容可以应用于@OneToMany但如前所述,我认为没有任何理由这样做并使不需要单独表的简单映射复杂化。

@JoinTable(joinColumns = @JoinColumn(name = "company_id", referencedColumnName = "company_id"),
               inverseJoinColumns = @JoinColumn(name = "bill_id", referencedColumnName = "bill_id") )

在这里查看更多信息Jpa 主键


推荐阅读