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

Java 如何级联删除属于jpa实体的集合?,java,hibernate,jpa,collections,playframework,Java,Hibernate,Jpa,Collections,Playframework,此操作始终无法删除实体,并出现以下错误: DELETE语句与引用约束“FK966F0D9A66DB1E54”冲突。冲突发生在数据库“TFADB”、表“dbo.MonthlyReport_categories”和列“MonthlyReport_id”中 如何指定映射,以便在删除报表时删除类别集合中的元素?级联删除(以及通常的级联操作)仅在通过EntityManager执行操作时有效。当通过JP-QL/HQL查询以批量删除的方式执行删除时,则不会执行此操作。当通过查询完成删除时,不能指定将删除链接到

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

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

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

级联删除(以及通常的级联操作)仅在通过
EntityManager执行操作时有效。当通过JP-QL/HQL查询以批量删除的方式执行删除时,则不会执行此操作。当通过查询完成删除时,不能指定将删除链接到
ElementCollection
中的元素的映射

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


您必须获取所有要删除的
月度报告
实体,然后调用
EntityManager。删除每个实体的
。看起来您也可以在实体中调用delete方法,而不是在游戏框架中调用该方法。

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

J.T.提供的答案是正确的,但对我和sebge2来说都不完整,正如他/她的评论中指出的那样。
@ElementCollection
@OnDelete
的组合还需要
@JoinColumn()

后续示例:

int n = MonthlyReport.delete("date = ?", date);
@实体
公共类报告扩展模型{
@身份证
@列(name=“report\u id”,columnDefinition=“BINARY(16)”)
public UUID id;//为使此实体具有主键而添加
公开日期;
公共双可用性;
@元素集合
@CollectionTable(name=“report\u category”,joinColumns=@JoinColumn(name=“report\u id”)//选择存储映射的DB表的名称
@MapKeyColumn(name=“fault\u category\u key”)//选择用于存储映射键的DB列的名称
@Column(name=“fault\u category\u value”)//选择用于存储映射值的DB列的名称
@JoinColumn(name=“report\u id”)//此实体的@id列的名称
@OnDelete(action=OnDeleteAction.CASCADE)
@级联(值={CascadeType.ALL})
公共地图类别;
}

此设置将创建一个名为
report
的表和另一个名为
report\u category
的表,其中包含三列:
report\u id、fault\u category\u key、fault\u category\u value
report\u category.report\u id
report.report\u id
之间的外键约束将在删除级联时被设置为
。我用Map测试了这个设置。

我遇到了同样的问题,下面是我的代码示例

@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;      
}
@ElementCollection
@CollectionTable(name=“table\u tag”,joinColumns=@JoinColumn(name=“data\u id”))
@MapKeyColumn(name=“name”)
@列(name=“content”)
私有地图标签
经过多次尝试,最后,我只是将table_tag.data_id的外键约束添加到父表的主键中。请注意,应设置为“删除级联到约束”。
您可以通过任何方式删除父实体,子元素集合也将被删除。

那么,删除类别的正确方式是什么?我注意到,如果我将外键设置为在数据库本身上级联,MonthyReport.delete实际上会成功-并逐个删除/删除。然后,删除将级联到类别。如果操作没有级联,该怎么办?JPA不支持对elementcollections(另请参见)org.hibernate.MappingException进行级联删除:在delete=“cascade”上只能使用反向一对多关联org.hibernate.AnnotationException:用
@OnDelete
注释的单向一对多关联必须定义
@JoinColumn
。附加的
@JoinColumn
帮助,请参见上面的答案。那么您如何删除元素集合?我使用@Query注释和JPQL删除父实体。但是,子元素集合不会被删除。@RocasYeh从技术上讲,这两种方案都应按预期工作:方案1)使用
crudepository
delete()
函数删除父实体,这意味着JPA将为您删除父项和所有子项。或者场景2)您将本机SQL与@Query一起使用,并对父实体行执行
DELETE
,RDBMS会根据
ON DELETE CASCADE
设置自动删除所有子实体。如果您无法隔离问题,请随意提出单独的问题并标记我。这是一个很棒的答案+1,从我自己的测试来看,我至少需要
@JoinColumn
@OnDelete
才能使其正常工作。
@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;      
}
@ElementCollection
@CollectionTable(name = "table_tag", joinColumns=@JoinColumn(name = "data_id"))
@MapKeyColumn(name = "name")
@Column(name = "content")
private Map<String, String> tags