【问题标题】:Automatically delete child entity using orphanRemoval Spring JPA使用 orphanRemoval Spring JPA 自动删除子实体
【发布时间】:2021-03-13 19:13:42
【问题描述】:

目前我有以下 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 标志已启用。

谁能告诉我如何通过调整上述2个实体的实体关系结构来实现这种关系?

【问题讨论】:

    标签: java spring-boot hibernate spring-data-jpa


    【解决方案1】:

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

    如果您更改并将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 primary key

    【讨论】:

    • 没有其中一个,多个 ID 无效。 - 不,这是有效的。但这是特定于休眠的,请参阅this
    • 你的意思是这个对spring Jpa有效?
    • 如果 hibernate 被用作 jpa 提供者,是的,这可能是复合标识符的映射
    • 是的,你说得对。但是,正如文档The restriction that a composite identifier has to be represented by a "primary key class" (e.g. @EmbeddedId or @IdClass) is only JPA-specific. 中所述,因此对于某些功能,它们超出了 JPA 规范的范围。
    • @Boug 是的,我对这两个实体都有一个单独的复合 ID 类。 mappedBy 是 @OneToMany 中的一个参数,而不是 @Column 子句此外,我什至无法使用 mappedBy 参数运行代码。它给了我以下错误 - Caused by: org.hibernate.AnnotationException: Associations marked as mappedBy must not define database mappings like @JoinTable or @JoinColumn: com.db.example.dbexample.entities.Bill.billLines
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多