对于实体“活动”和“发票”,我有多对多的单向映射。映射仅在Activity实体中设置(我不需要来自Invoice端的访问活动)。
@ManyToMany
@JoinTable(name = "OP_ACTIVITY_INVOICE_XREF", joinColumns = @JoinColumn(name = "ACTIVITY_ID", referencedColumnName = "OBJECT_ID"), inverseJoinColumns = @JoinColumn(name = "INVOICE_ID", referencedColumnName = "OBJECT_ID"))
private Set<Invoice> invoices;
插入和更新工作正常,但我在删除活动时遇到问题。删除活动代码如下:
activity.getInvoices().clear();
em.remove(activity);
当我运行这些代码时,我认为em将首先从连接表中删除记录,然后删除活动记录(发票记录应保持不变)。但是连接表中的记录永远不会被删除。我收到这个外键错误:
[STDOUT] Hibernate: delete from OP_ACTIVITY where OBJECT_ID=?
[JDBCExceptionReporter] SQL Error: 1451, SQLState: 23000
ERROR [JDBCExceptionReporter] Cannot delete or update a parent row: a foreign key constraint fails (`prod/op_activity_invoice_xref`.......
我在这里做错了什么?请帮助,谢谢。
答案 0 :(得分:1)
我认为你需要 @ManyToMany(cascade = {CascadeType.REMOVE})
选项。
CascadeType.REMOVE:删除实体时,也删除实体 在这个领域举行。
活动:
@ManyToMany(cascade = {CascadeType.REMOVE})
@JoinTable(name = "OP_ACTIVITY_INVOICE_XREF", joinColumns = @JoinColumn(name = "ACTIVITY_ID", referencedColumnName = "OBJECT_ID"), inverseJoinColumns = @JoinColumn(name = "INVOICE_ID", referencedColumnName = "OBJECT_ID"))
private Set<Invoice> invoices;
显然REMOVE不应与@ManyToMany一起使用(来自JPA 2.0规范):
关系建模注释约束了使用 cascade = REMOVE规范。级联= REMOVE规范应该 仅适用于指定为OneToOne或的协会 一对多。将cascade = REMOVE应用于其他应用程序的应用程序 协会不可携带。
您可以在Hibernate中尝试供应商扩展@OnDelete:
@OnDelete(动作= OnDeleteAction.CASCADE)
或者你可以手动完成:
for (Invoice invoice : activity.getInvoices()) {
em.remove(invoice);
}
activity.getInvoices().clear();
em.remove(activity);
... flush() etc...
或者你可以注释@PreRemove: 将以下方法添加到不是关系所有者的实体(发票)
@PreRemove
private void removeInvoicesFromActivities() {
for (Activity a : activities) {
a.getInvoices().remove(this);
}
}