#java #hibernate #jpa
#java #переход в спящий режим #jpa
Вопрос:
Мне трудно понять, какие минимальные усилия необходимы с моей стороны для удаления сущности из отношений OneToMany. Я нахожу много примеров, просто добавляющих сущности в эти наборы (и это работает нормально), но удаление сущностей найти гораздо сложнее.
У меня есть следующий класс:
@Entity
public class Product {
...
OneToMany(mappedBy="product", orphanRemoval=true,
cascade={CascadeType.DETACH,CascadeType.MERGE,CascadeType.PERSIST,CascadeType.REFRESH},fetch=FetchType.EAGER)
Set<Expert> experts = new HashSet<Expert>();
...
}
@Entity
public class Expert {
...
@ManyToOne(optional=false)
Product product;
@ManyToOne(optional=false)
Person person;
...
}
(Person похож на Product)
У меня он заполнен продуктами и экспертами. Я хочу удалить эксперта из списка продуктов, чтобы экспертный объект был полностью удален. Я ожидал бы, что либо следующего кода будет достаточно:
Product aProduct = findAProduct(...);
Expert anExpert aProduct.getExperts.get(...); // Just get the first expert that I want removed
EntityManager em = entityManager();
em.getTransaction().begin();
aProduct.getExperts().remove(anExpert);
em.merge(aProduct);
em.getTransaction().commit();
или:
em.getTransaction().begin();
em.remove(anExpert);
em.getTransaction().commit();
Это слишком упрощенно? Что делает JPA и что я должен сделать сам? Я уже решал эту проблему раньше, просто используя запросы, но я ожидаю, что JPA сможет сделать это за меня.
Комментарии:
1. Вы пробовали эти два метода? Что это дает?
Ответ №1:
Попробуйте:
em.getTransaction().begin();
aProduct = em.merge(aProduct);
aProduct.getExperts().remove(anExpert);
em.getTransaction().commit();
Проблема связана с операцией слияния, а не с удалением.
Ответ №2:
Исходя из моего прошлого опыта, удаление дочернего элемента в двунаправленных отношениях родитель-потомок в режиме гибернации может быть очень сложным.
Обычно я использую вместо этого однонаправленное отображение, т. Е. Продукт не содержит набор экспертов. Но вы можете реализовать средство получения, чтобы получить всех экспертов, используя вызов Hibernate. Преимущества заключаются в:
- упрощение сопоставления
- упрощение кодирования
- управляемое поведение
Вы всегда можете вернуться и реализовать кэширование или быструю выборку на более позднем этапе. И большую часть времени они являются ненужной предварительной оптимизацией.
Ответ №3:
Способ заставить его работать заключался в следующем:
EntityManager em = entityManager();
// Retrieve the expert in the new EntityManager context
Expert expertToDelete = em.find(Expert.class, anExpert.id);
em.getTransaction().begin();
expertToDelete.getProduct().getExperts().remove(expertToDelete);
expertToDelete.getPerson().getExperts().remove(expertToDelete);
em.remove(expertToDelete);
em.getTransaction().commit();
Вполне может быть, что вместо получения эксперта с помощью find вы можете использовать merge() вместо anExpert, но, похоже, вышеприведенное работает.