如何级联删除作为jpa实体一部分的集合?

emt*_*t14 16 java collections hibernate jpa playframework

@Entity
public class Report extends Model {

    public Date date;
    public double availability;

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

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

int n = MonthlyReport.delete("date = ?", date);
Run Code Online (Sandbox Code Playgroud)

这总是无法删除具有以下错误的实体:

DELETE语句与REFERENCE约束"FK966F0D9A66DB1E54"冲突.冲突发生在数据库"TFADB",表"dbo.MonthlyReport_categories",列"MonthlyReport_id"中.

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

Mik*_*unu 28

级联删除(以及一般的级联操作)仅在通过操作完成时才有效EntityManager.不是通过JP QL/HQL查询以批量删除方式完成删除.在ElementCollection通过查询执行删除时,您无法指定将删除链接到元素的映射.

ElementCollection注释没有级联属性,因为操作总是级联的.当您删除实体时EntityManager.remove(),操作会级联到ElementCollection.

您必须获取MonthlyReport要删除的所有实体并EntityManager.remove为每个实体调用它们.在Play框架中看起来不是这样,你也可以在实体中调用delete-method.


J.T*_*.T. 6

我们找到了神奇的票!将OnDelete(action= OnDeleteAction.CASCADE)添加到 ElementCollection。这允许我们从 SQL 中删除项目(在 entityManager 之外)。

  • org.hibernate.AnnotationException:用“@OnDelete”注释的单向一对多关联必须定义“@JoinColumn”。额外的“@JoinColumn”有帮助,请参阅上面的答案 (3认同)
  • org.hibernate.MappingException:只有反向一对多关联可以使用 on-delete="cascade" (2认同)

小智 5

JT 提供的答案是正确的,但正如他/她的评论中指出的那样,对我和 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;      
}
Run Code Online (Sandbox Code Playgroud)

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

  • 这是一个很棒的答案+1,根据我自己的测试,我至少需要“@JoinColumn”和“@OnDelete”才能使其正常工作。 (3认同)