我有实体“事件”和“发票”的单向多对多映射。映射仅在事件实体中设置(我不需要从发票端访问事件)。
@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);
当我运行这些代码时,我认为他们会首先从连接表中删除记录,然后删除事件记录(发票记录应保持不变)。但连接表中的记录永远不会被删除。我收到此外键错误:
[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`.......
我在这里做错了什么?请帮忙,谢谢。
最佳答案
我认为您需要@ManyToMany(cascade = {CascadeType.REMOVE})
选项。
CascadeType.REMOVE: When deleting an entity, also delete the entities held in this field.
事件中:
@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 规范)一起使用:
The relationship modeling annotation constrains the use of the cascade=REMOVE specification. The cascade=REMOVE specification should only be applied to associations that are specified as OneToOne or OneToMany. Applications that apply cascade=REMOVE to other associations are not portable.
您可以在 Hibernate 中尝试供应商扩展@OnDelete:
@OnDelete(action=OnDeleteAction.CASCADE)
或者您可以手动执行:
for (Invoice invoice : activity.getInvoices()) {
em.remove(invoice);
}
activity.getInvoices().clear();
em.remove(activity);
... flush() etc...
或者你可以注释@PreRemove: 将以下方法添加到不是关系所有者的实体(Invoice)
@PreRemove
private void removeInvoicesFromActivities() {
for (Activity a : activities) {
a.getInvoices().remove(this);
}
}
关于hibernate - JPA:如何删除单向多对多关系中的链接记录?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20627270/