JPA CascadeType.REMOVE не работает

У меня есть две сущности Бизнес, которые состоят из списка Отделов.

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

  private static final long serialVersionUID = 1L;

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Column(name = "Id")
  private Long id;

  @OneToMany(mappedBy = "business", 
       cascade = {CascadeType.PERSIST, CascadeType.REMOVE})
   private List<Department> departments;

   @OneToMany(mappedBy = "business", orphanRemoval = true, 
     cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE})
   private List<Process> processs;

   @ManyToMany
   private List<Competence> competences;
}


@Entity
@Table(name = "Department")
public class Department implements Serializable {
   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   private Long id;

   @OneToMany(mappedBy = "father", 
        cascade = {CascadeType.PERSIST, CascadeType.REMOVE})
   private List<Department> departments;
}

Когда я пытаюсь удалить бизнес-экземпляр, я получаю исключение Mysql.

Невозможно удалить или обновить родительскую строку: ограничение внешнего ключа не работает (evac_java.Department, CONSTRAINT FK_Department_Business FOREIGN KEY (Business) REFERENCES Business (Id)):HY000 — null

Это означает, что я не могу удалить бизнес-экземпляр, потому что с ним связаны отделы, но отдел не может существовать сам по себе, поэтому я хочу удалить все бизнес-отделы при его удалении. Я думал, что добьюсь этого, добавив cascade = CascadeType.REMOVE в аннотацию @OneToMany в бизнес-объекте, но это не работает.

Я провел поиск в сети и нашел много вопросов, похожих на этот, в stackoverflow, но все они предполагают одно и то же: add cascade = CascadeType.REMOVE или CascadeType.ALL

Поэтому мне интересно, если я что-то пропустил.

Я использую Glassfish 4.1 и EclipseLink.

я пробовал с

@OneToMany(mappedBy = "business", orphanRemoval = true)
private List<Department> departments;

на хозяйственном объекте, но он тоже не работает

Вот метод, который я использую для удаления сущностей, объявленных в абстрактном классе.

public void remove(T entity) {
    getEntityManager().remove(getEntityManager().merge(entity));
}

person Armando    schedule 19.04.2015    source источник
comment
я думаю, вы должны добавить orphanremoval = true заголовок вашего списка, который вы хотите удалить элемент   -  person Sarkhan    schedule 19.04.2015
comment
Я рассматривал этот вариант, но не является ли он избыточным с CascadeType.REMOVE, а также более агрессивным? и в этом случае это должно сработать, но что, если мне не нужно удалять детей?   -  person Armando    schedule 19.04.2015
comment
если это отношение onetomany, это означает, что дети не могут существовать без отцовского класса. Поэтому, если вы удаляете отцовский класс, это означает, что вы должны удалить связанные элементы или обновить связанный столбец null   -  person Sarkhan    schedule 19.04.2015
comment
stackoverflow.com/questions/18813341/   -  person Sarkhan    schedule 19.04.2015
comment
Вы пробовали использовать обе опции orphanRemoval и cascade? Удаление потерянных строк просто говорит об удалении потерянных строк (это поведение, которое вы хотите), а параметр каскада просто говорит, что нужно инициировать удаление при удалении стороны-владельца. Определены ли у вас какие-либо дополнительные FK, помимо того, что у вас есть здесь? Как выглядит сгенерированный DDL и какая реализация JPA?   -  person John Ament    schedule 20.04.2015
comment
Я пробовал варианты «orphanRemoval» и «cascade». Я использую JPA 2.0 с EclipseLink на Glassfish 4.1. Я отредактировал свой вопрос, чтобы показать другие отношения.   -  person Armando    schedule 20.04.2015
comment
В базе данных FK «FK_Department_Business» в таблице «Department», которая ссылается на «Business». «Id» говорит ON DELETE -> RESTRICTED и ON UPDATE -> RESTRICTED. Очевидно, что это не генерируется должным образом   -  person Armando    schedule 20.04.2015
comment
Вы проверили, что в вашей коллекции отделов в вашем бизнес-экземпляре есть отделы, когда ваш вызов удаляет бизнес-объект? JPA может удалять и каскадировать удаление только тех сущностей, о которых он знает, и если вы не поддерживали обе стороны этого двунаправленного отношения, возникнут подобные проблемы. Если он пуст, попробуйте em.refresh() перед удалением, заставив JPA заполнить все отношения, чтобы их можно было правильно удалить, хотя, если это работает, вам лучше сохранить отношения.   -  person Chris    schedule 22.04.2015
comment
Вот и все, @Chris, когда я сохранил отдел, я установил его бизнес, но я не добавил новый отдел в список бизнес-отделов. Если вы опубликуете свой комментарий в качестве ответа, я приму его.   -  person Armando    schedule 24.04.2015


Ответы (1)


JPA может удалять и каскадировать удаление только тех сущностей, о которых он знает, и если вы не поддерживали обе стороны этого двунаправленного отношения, возникнут подобные проблемы. Если коллекция отделов пуста, попробуйте em.refresh() перед удалением, заставив JPA заполнить все отношения, чтобы их можно было правильно удалить, хотя лучше поддерживать обе стороны отношения по мере внесения изменений, чтобы избежать удар по базе данных.

person Chris    schedule 27.04.2015