Невозможно удалить родительскую строку с отношением JPA @OneToMany

В моем приложении Java EE у меня есть два постоянных объекта Worklist и Task со следующими отношениями JPA:

Worklist сущность:

 public class WorkList implements Serializable {
    ...
    @OneToMany(cascade={CascadeType.PERSIST, CascadeType.REMOVE} , mappedBy ="worklist")
    private List<Task> tasks;
    ...
    }

И объект Task:

  public class Task implements Serializable {
    ...
    @ManyToOne
    private WorkList worklist;
    ...
    }

Я указал тип каскада в Worklist как:

  cascade={CascadeType.PERSIST, CascadeType.REMOVE}

Итак, я могу сохранить Worklist и список tasks, которые связаны с этим Worklist, но у меня возникает проблема, когда я пытаюсь удалить Worklist, и у меня есть это исключение:

Avertissement: Local Exception Stack: 
Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.2.v20111125-r10461):  
org.eclipse.persistence.exceptions.DatabaseException
Internal Exception:  
com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot  
delete or update a parent row: a foreign key constraint fails (`scopedata`.`TASKS`, 
CONSTRAINT `FK_TASKS_WORKLIST_id` FOREIGN KEY (`WORKLIST_id`) REFERENCES `WORKLISTS` 
(`id`))
Error Code: 1451
Call: DELETE FROM WORKLISTS WHERE ((id = ?) AND (version = ?))
bind => [2 parameters bound]
Query: DeleteObjectQuery(WokList{id=bbf05bdb-1314-4b07-9f4e-69898b800c00, creation=Thu
Nov 28 08:39:21 CET 2013, startDate=Thu Nov 07 00:00:00 CET 2013, endDate=Fri Nov 15
00:00:00 CET

С другой стороны, я могу успешно удалить файл Task.

Это метод в WorklistManager.java, который удаляет рабочий список.

   @Override
     public boolean deleteWorkList(WorkList workList) {
       if (findWorkList(workList)) {
        em.remove(em.merge(workList));
        return true;
    }
    return false;
    }

Затем я вызываю этот метод в управляемом компоненте:

    public String deleteWorkList() {
    workListManagerLocal.deleteWorkList(selectedWorkList);
    return "index";
  }

Я работаю с: JPA2 и Glassfish 3.1.2.2.


person Reem    schedule 28.11.2013    source источник
comment
Пожалуйста, просмотрите эту тему: stackoverflow .com/questions/306144/ Мне кажется, что поведение удаления сирот очень специфично для реализации. Но посмотрите сами!   -  person Balázs Németh    schedule 28.11.2013
comment
Зарегистрируйте SQL-запросы, сделанные EclipseLink, и опубликуйте их в своем вопросе. Кажется, что порядок SQL-запросов неверен.   -  person Andrei I    schedule 28.11.2013
comment
@AndreiI Теперь это работает, но только в первый раз после запуска проекта, во второй раз отображается то же исключение. На самом деле у меня есть две таблицы данных. Первый показывает все рабочие списки, затем пользователь выбирает один, чтобы отобразить список связанных задач (вторая таблица данных). Итак, я внедрил управляемый компонент Worklist в управляемый компонент Task, чтобы восстановить идентификатор selectedWorklist.   -  person Reem    schedule 28.11.2013
comment
Когда вы собираетесь удалить рабочий список, что находится в наборе задач рабочего списка? Могу поспорить, что вы не поддерживаете обе стороны двунаправленных отношений, поэтому задачи ссылаются на рабочий список, но эти рабочие списки не имеют ссылок на задачи. В этом случае каскадное удаление не будет работать, поскольку JPA не может знать о других задачах, которые необходимо очистить. JPA не выполняет обслуживание отношений — приложение должно поддерживать синхронизацию обеих сторон двунаправленных отношений друг с другом.   -  person Chris    schedule 02.12.2013


Ответы (1)


  1. Добавьте свойство orphanRemoval=true к отношениям @OneToMany.
  2. Вместо вызова em.merge() в вашем public boolean deleteWorkList(WorkList workList) сделайте managedWorklist = em.find(Worklist.class, workList.getId()), а затем удалите возвращенный рабочий список: em.remove(managedWorklist) и НЕ ВЫЗЫВАЙТЕ findWorkList(), поскольку вы уже делаете это в своем коде.
person Andrei I    schedule 28.11.2013