2013-12-17 94 views
1

我有一個單向多對多的實體'活動'和'發票'映射。該映射僅在Activity實體中設置(我不需要從Invoice端訪問活動)。JPA:如何刪除單向多對多關係中的鏈接記錄?

@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`....... 

我在做什麼錯在這裏?請幫助,謝謝。

回答

1

我認爲你需要@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.

你可以試試供應商擴展@OnDelete在休眠:

@OnDelete(action=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); 
    } 
} 
+0

嘗試添加cascadeType.remove選項,但沒有區別。它不會刪除鏈接記錄,所以我仍然收到相同的錯誤。 – user3109865

+0

嗯,是的,我更新了我的答案 –

+0

感謝您的幫助,事實證明我的問題與其他問題有關。這是刪除鏈接記錄的正確方法(正如我之前所說的,我不想刪除發票): 'activity.getInvoices()。clear(); em.remove(activity);' – user3109865

相關問題