Почему JPA не удаляет принадлежащие объекты, если объект-владелец теряет ссылку на них?
-
16-09-2019 - |
Вопрос
У меня есть объект JPA «Запрос», которому принадлежит список ответов (также объекты JPA).Вот как это определено в Request.java:
@OneToMany(cascade= CascadeType.ALL, mappedBy="request")
private List<Answer> answerList;
И в Answer.java:
@JoinColumn(name = "request", referencedColumnName="id")
@ManyToOne(optional = false)
private Request request;
В ходе выполнения программы в список ответов запроса могут быть добавлены или удалены ответы, а также может быть заменен фактический объект списка.Моя проблема такова:когда я объединяю запрос с базой данных, объекты ответа, которые использовал быть в списке, сохраняются в базе данных, то есть объекты ответа, на которые запрос больше не содержит ссылку (косвенно, через список), не удаляются.
Это не то поведение, которое мне нужно, поскольку если я объединяю запрос в базу данных, а затем получаю его снова, его список ответов может не совпадать.Я делаю какую-то ошибку в программировании?Существует ли аннотация или настройка, которая гарантирует, что ответы в базе данных будут именно ответами в списке запросов?
Решение состоит в том, чтобы сохранить ссылки на исходный список ответов, а затем использовать EntityManager для удаления каждого старого ответа перед объединением запроса, но похоже, что должен быть более чистый способ.
Решение
В JPA 1.0 то, что вы хотите сделать, не может быть выполнено JPA.Проще говоря, все управление отношениями должно выполняться приложением, включая удаление всех потерянных элементов из коллекций (именно это вы и пытаетесь сделать).
В JPA 2.0 они поддерживаются (хотя подробностей я не знаю), но в зависимости от вашей реализации обновление может быть непростым или невозможным.
Вы также можете использовать что-то вроде Hibernate напрямую, но при этом использовать множество аннотаций JPA 1.0 и т. д.Я также не могу предоставить подробную информацию об этом.
В моем случае я написал общий код для автоматического объединения коллекций посредством отражения.
Другие советы
Использование EclipseLink и добавление аннотации @PrivateOwned в список ответов поможет.
Недопустимо указывать дополнительные свойства в отображаемом отношении.Вместо этого вы можете использовать аннотацию @DependentElement в Request.
Если вы используете Hibernate в качестве поставщика JPA, вы можете добавить
@Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
в списке ответов.Это будет работать в дополнение к аннотациям JPA, которые вы там уже используете.JPA 2 (большинство/все поставщики JPA в настоящее время не имеют готовой к использованию реализации) может сделать это самостоятельно.