Итак, вот как это должно работать в соответствии со спецификацией (во время компиляции и при условии правильной навигации по документам):
Компилятор идентифицирует список методы сопоставления из типа D
и его базовых типов, основанные на имени метода и списке аргументов. Это означает, что любой метод с именем Foo
, принимающий один параметр типа, для которого существует неявное преобразование из B
, является допустимым кандидатом. Это приведет к следующему списку:
C.Foo(B) (public virtual)
D.Foo(B) (public override)
D.Foo(A) (public)
Из этого списка исключаются любые объявления, содержащие модификатор переопределения. Это означает, что список теперь содержит следующие методы:
C.Foo(B) (public virtual)
D.Foo(A) (public)
. В этот момент у нас есть список подходящих кандидатов, и теперь компилятор должен решить, что вызывать. В документе 7.5.5.1 Вызов метода мы находим следующий текст:
Если N применимо относительно A (). Раздел 7.4.2.1 ), то все методы, объявленные в базовом типе T, удаляются из набора.
blockquote>Это по существу означает, что если есть применимый метод, объявленный в
D
, любые методы из базовые классы будут удалены из списка. На этом этапе у нас есть победитель:D.Foo(A) (public)
] поведение JPA корректно (имеется в виду [] в соответствии со спецификацией []): объекты не удаляются просто потому, что вы удалили их из коллекции OneToMany. Существуют расширения, специфичные для конкретного производителя, но встроенные в JPA, они не подходят.[
] []Частично это происходит потому, что JPA на самом деле не знает, следует ли удалять что-то, удаленное из коллекции. В терминах объектного моделирования это разница между []составом [] и "агрегированием*. [
] [] В []составе [] дочерняя сущность не существует без родителя. Классический пример - между домом и комнатой. Удаление дома и комнаты тоже идет.[
] [][]Агрегация[] является более слабым видом ассоциации и типизируется как "Курс", так и "Студент". Удалите Курс, и Студент все еще существует (вероятно, в других курсах).[
] []Так что вам нужно либо использовать расширения, специфичные для производителя, чтобы заставить это поведение (если доступно), либо явно удалить ученика и удалить его из родительской коллекции.[
] []Я знаю:[
] [] В дополнение к ответу cletus, []JPA 2.0[], последний с декабря 2010 года, вводит атрибут []orphanRemoval[
] в аннотации []@OneToMany[
].
Для более подробной информации смотрите запись в блоге [] []. [
] Обратите внимание, что поскольку спецификация относительно новая, не все провайдеры JPA 1 имеют окончательную реализацию JPA 2. Например, версия []Hibernate 3.5.0-Beta-2[] еще не поддерживает этот атрибут.[
].] Здесь каскад, в контексте удаления, означает, что дети удаляются, если вы удаляете родителя. Не ассоциация. Если вы используете Hibernate в качестве поставщика JPA, вы можете сделать это, используя []специальный каскад в режиме гибернации[].[
].Как было объяснено, с JPA невозможно делать то, что я хочу, поэтому я использовал hibernate.cascade annotation, при этом соответствующий код в классе Parent теперь выглядит следующим образом:
@OneToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH}, mappedBy = "parent")
@Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE,
org.hibernate.annotations.CascadeType.DELETE,
org.hibernate.annotations.CascadeType.MERGE,
org.hibernate.annotations.CascadeType.PERSIST,
org.hibernate.annotations.CascadeType.DELETE_ORPHAN})
private Set<Child> childs = new HashSet<Child>();
Я не мог просто использовать 'ВСЕ', так как это удалило бы и родителя.