2013-12-17 77 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

相关问题