Ошибки @OneToMany в MySQL: невозможно удалить или обновить родительскую строку: сбой ограничения внешнего ключа - PullRequest
3 голосов
/ 25 декабря 2011

У меня отношение «один ко многим» выглядит следующим образом

@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;
}

Когда я хочу удалить ReminderHeader из базы данных MySQL следующим образом

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 Ответ

6 голосов
/ 25 декабря 2011

У вас есть две ошибки.

Первая ошибка: вы связали двунаправленную связь между заголовком и деталями дважды: один раз в заголовке и один раз в деталях. При наличии двунаправленной связи одна из сторон (в данном случае сторона заголовка) должна быть объявлена ​​как обратная сторона другой стороны с использованием атрибута mappedBy:

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

Вторая ошибка: каскад DELETE применяется только при использовании метода Session.delete() для удаления объекта. Запросы на удаление полностью игнорируют сеанс (это означает, что сущности, удаленные запросом, но ранее загруженные, остаются в сеансе в том же состоянии, как если бы ни один запрос не был выполнен).

Таким образом, для каскадного удаления необходимо выполнить запрос на выборку, чтобы найти все заголовки для удаления, а затем выполнить цикл по этим заголовкам и удалить их, используя session.delete().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...