MySQL中的@OneToMany错误:无法删除或更新父行:外键约束失败

时间:2011-12-25 10:36:19

标签: java mysql hibernate jpa

我有如下的一对多关系

@Entity
@Table(name = "reminderheader")
public class ReminderHeader implements Serializable {

    @Id
    @org.hibernate.annotations.GenericGenerator(name = "REMINDER_HEADER_GEN", strategy = "native")
    @GeneratedValue(generator = "REMINDER_HEADER_GEN")
    @Column(name = "id", unique = true, nullable = false)
    @Basic(fetch = FetchType.EAGER)
    private long id;

    @OneToMany(fetch = FetchType.EAGER, orphanRemoval = true)
    @Cascade(value = { CascadeType.SAVE_UPDATE, CascadeType.DELETE })
    @JoinColumn(name = "HeaderID")
    @Fetch(FetchMode.SELECT)
    private Set<ReminderDetails> reminderDetailslist;
}

@Entity
@Table(name = "reminderdetails")
public class ReminderDetails implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", unique = true, nullable = false)
    @Basic(fetch = FetchType.EAGER)
    private long id;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "HeaderID", nullable = false)
    private ReminderHeader reminderHeader;
}

当我想从MySQL数据库中删除ReminderHeader时,如下所示

String query = "delete ReminderHeader rHdr where rHdr.recipientGUID = :rHeaderGUID ";
Query myQry = getCurrentSession().createQuery(query);
myQry.setString("rHeaderGUID", RemHeaderGUID);
int deletedRow = myQry.executeUpdate();

然后我收到以下错误

  

无法删除或更新父行:外键约束失败

如何在不收到此错误的情况下删除ReminderHeader及其ReminderDetails个孩子?


更新:我更改了一对多关系,如下所示:

@OneToMany(fetch = FetchType.EAGER, orphanRemoval = true, mappedBy = "reminderHeader")
@Cascade(value = { CascadeType.SAVE_UPDATE, CascadeType.DELETE })
@Fetch(FetchMode.SELECT)
private Set<ReminderDetails> reminderDetailslist;

@ManyToOne(fetch = FetchType.EAGER)
private ReminderHeader reminderHeader;

我使用以下方法删除

String query = "From ReminderHeader rHdr where rHdr.recipientGUID = :rHeaderGUID ";
Query myQry = getCurrentSession().createQuery(query);
myQry.setString("rHeaderGUID", RemHeaderGUID);
List<ReminderHeader> remList = myQry.list();
for (int i = 0; i < remList.size(); i++) {
    getCurrentSession().delete(remList.get(i));
}

但它没有改变数据库中的任何内容,也没有出现错误或异常。

1 个答案:

答案 0 :(得分:6)

你有两个错误。

第一个错误:您在标题和详细信息之间映射了两次双向关联:一次在标题中,一次在详细信息中。当您具有双向关联时,必须使用mappedBy属性将其中一方(在这种情况下为一个标题侧)声明为另一方的反转:

@OneToMany(fetch = FetchType.EAGER, orphanRemoval = true, mappedBy = "reminderHeader")
@Cascade(value = { CascadeType.SAVE_UPDATE, CascadeType.DELETE })
@Fetch(FetchMode.SELECT)
private Set<ReminderDetails> reminderDetailslist;

第二个错误:只有在使用Session.delete()方法删除实体时才会应用DELETE级联。删除查询完全绕过会话(意味着查询删除但之前加载的实体保留在会话中,状态与未执行查询的状态相同)。

因此,要级联删除,您必须执行选择查询以查找要删除的所有标头,然后循环使用这些标头并使用session.delete()将其删除。