Почему JPA не удаляет принадлежащие сущности, когда сущность-владелец теряет ссылку на них?

У меня есть объект JPA «Запрос», которому принадлежит список ответов (также объекты JPA). Вот как это определено в Request.java:

@OneToMany(cascade= CascadeType.ALL, mappedBy="request")
private List<Answer> answerList;

И в ответе.java:

@JoinColumn(name = "request", referencedColumnName="id")
@ManyToOne(optional = false)
private Request request;

В ходе выполнения программы в список ответов запроса могут быть добавлены или удалены ответы, или фактический объект списка может быть заменен. Моя проблема заключается в следующем: когда я объединяю запрос в базу данных, объекты ответа, которые использовались в списке, сохраняются в базе данных, то есть объекты ответа, которые запрос больше не содержит. ссылки на (косвенно, через Список) не удаляются.

Это не то поведение, которое мне нужно, так как если я объединяю запрос в базу данных, а затем снова извлекаю его, его список ответов может быть другим. Я делаю какую-то ошибку программирования? Есть ли аннотация или настройка, которая гарантирует, что ответы в базе данных точно соответствуют ответам в списке запросов?

Решение состоит в том, чтобы сохранить ссылки на исходный список ответов, а затем использовать EntityManager для удаления каждого старого ответа перед объединением запроса, но, похоже, должен быть более чистый способ.


person Nick    schedule 15.07.2009    source источник


Ответы (4)


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

В JPA 2.0 они поддерживаются (хотя я не знаю подробностей), но в зависимости от вашей реализации обновление может оказаться непростым или невозможным.

Вы также можете напрямую использовать что-то вроде Hibernate, но по-прежнему использовать много аннотаций JPA 1.0 и т. д. Я также не могу предоставить подробности об этом.

В моем случае я написал общий код для автоматического объединения коллекций посредством отражения.

person Will Hartung    schedule 15.12.2009
comment
В Hibernate это можно сделать с помощью CascadeType.DELETE_ORPHAN. - person Don Roby; 02.03.2010

Использование EclipseLink и добавление аннотации @PrivateOwned к answerList может помочь.

person Olli Knuuttila    schedule 06.05.2010

Запрещается указывать дополнительные свойства в отображаемом отношении. Вместо этого вы можете использовать аннотацию @DependentElement в запросе.

person oakjumper    schedule 15.12.2009

Если вы используете Hibernate в качестве поставщика JPA, вы можете добавить

@Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN)

в списке ответов. Это будет работать в дополнение к аннотациям JPA, которые вы уже используете. JPA 2 (большинство/все провайдеры JPA в настоящее время не имеют готовой к производству реализации) может сделать это самостоятельно.

person bert    schedule 06.05.2010