如何级联删除属于 JPA 实体的集合?

@Entity
public class Report extends Model {

    public Date date;
    public double availability;

    @ElementCollection
    @Cascade(value={CascadeType.ALL})
    public Map<FaultCategory, Integer> categories;      
}

在我的一份工作中,我有以下代码:

int n = MonthlyReport.delete("date = ?", date);

这始终无法删除实体,并出现以下错误:

DELETE 语句与引用约束“FK966F0D9A66DB1E54”冲突。冲突发生在数据库“TFADB”,表“dbo.MonthlyReport_categories“,”MonthlyReport_id“列。

如何指定映射,以便在删除报表时删除集合中的元素?categories


答案 1

级联删除(以及一般的级联操作)仅在通过 完成操作时才有效。当删除是通过 JP QL /HQL 查询作为批量删除完成的时,则不然。当通过查询完成删除时,不能指定将删除链接到元素的映射。EntityManagerElementCollection

ElementCollection注记没有级联属性,因为操作始终是级联的。通过 删除实体时,操作将级联到 。EntityManager.remove()ElementCollection

您必须获取要删除的所有实体并调用每个实体。在 Play 框架中,您还可以在实体中调用 delete-method,而不是这样。MonthlyReportEntityManager.remove


答案 2

J.T.提供的答案是正确的,但正如我和sebge2在他/她的评论中指出的那样,答案并不完整。的组合和进一步要求。@ElementCollection@OnDelete@JoinColumn()

后续示例:

@Entity
public class Report extends Model {
    @Id
    @Column(name = "report_id", columnDefinition = "BINARY(16)")
    public UUID id; // Added for the sake of this entity having a primary key
    public Date date;
    public double availability;

    @ElementCollection
    @CollectionTable(name = "report_category", joinColumns = @JoinColumn(name = "report_id")) // choose the name of the DB table storing the Map<>
    @MapKeyColumn(name = "fault_category_key") // choose the name of the DB column used to store the Map<> key
    @Column(name = "fault_category_value")     // choose the name of the DB column used to store the Map<> value
    @JoinColumn(name = "report_id")            // name of the @Id column of this entity
    @OnDelete(action = OnDeleteAction.CASCADE)
    @Cascade(value={CascadeType.ALL})
    public Map<FaultCategory, Integer> categories;      
}

此设置将创建一个名为的表和另一个包含三列的表:。和 之间的外键约束将为 。我用Map<String,String>测试了这个设置。reportreport_categoryreport_id, fault_category_key, fault_category_valuereport_category.report_idreport.report_idON DELETE CASCADE