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

时间:2011-10-08 09:08:45

标签: java hibernate jpa collections playframework

@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语句与REFERENCE约束“FK966F0D9A66DB1E54”冲突。冲突发生在数据库“TFADB”,表“dbo.MonthlyReport_categories”,列'MonthlyReport_id'。

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

4 个答案:

答案 0 :(得分:27)

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

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

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

答案 1 :(得分: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;      
}

此设置将创建一个名为report的表和另一个具有三列的表report_categoryreport_id, fault_category_key, fault_category_valuereport_category.report_idreport.report_id之间的外键约束为ON DELETE CASCADE。我使用Map 测试了此设置。

答案 2 :(得分:0)

我遇到了同样的问题,这是我的代码示例。

@ElementCollection
@CollectionTable(name = "table_tag", joinColumns=@JoinColumn(name = "data_id"))
@MapKeyColumn(name = "name")
@Column(name = "content")
private Map<String, String> tags

最后,经过大量尝试,我只是将table_tag.data_id的外键约束添加到父表的主键中。注意,您应该将ON DELETE CASCADE设置为约束。 您可以通过任何方式删除父实体,子元素集合也将被删除。

答案 3 :(得分:-1)

我们找到了魔术票!将 OnDelete(action = OnDeleteAction.CASCADE)添加到ElementCollection。这使我们可以从SQL(在entityManager外部)删除该项目。