JPA / Hibernate удалить объект иногда не работает
у меня есть следующий код, который обычно хорошо работает:
public void delete(T object)
{
EntityManager em = getPersistence().createEntityManager();
EntityTransaction et = em.getTransaction();
try
{
et.begin();
object = em.find(object.getClass(), object.getId());
em.remove(object);
em.flush();
et.commit();
}
catch(Exception e)
{
error("Unable to delete " + object.toString() + ": there are references to it.");
}
finally
{
if (et.isActive()) et.rollback();
em.close();
}
}
для многих моих классов сущностей, это просто работает. Однако для двух из них он ничего не делает, не создает никаких исключений и не удаляет объект. Журнал из hibernate показывает, что hibernate выполняет несколько запросов select, но даже не пытается выполнить удаление.
Я уже пробовал предложения, найденные в других подобных вопросах здесь и здесь, но безрезультатно (ну, последнее предполагает @Transactional
который я не могу использовать, но я просто вложил операторы между begin()
и ).
Я не могу найти, что эти два класса имеют больше (или меньше), чем другие. Они используют @PrimaryKeyJoinColumn
как и почти все другие сущности, которые у меня есть, у них есть @OneToMany
и @ManyToOne
как и другими людьми. Честно говоря, у них есть @OneToOne(optional = false)
поле, которое ссылается на другой класс, и что другие лица не имеют, но я не будет проходить через хлопоты изменения этого (и, следовательно, изменения схемы базы данных), если вы не скажете мне, что для этого может быть причина.
Is @OneToOne
ответственность? Или мой код удаления прослушивается?
3 ответов
есть ли у вас ассоциации в этом графике, которые каскадируют сохранение обратно к удаляемой вещи? Если это так, спецификация JPA четко указывает, что поставщик должен отменить удаление в таком случае. Если это так,Hibernate записывает инструкцию журнала, говорящую "удаление объекта un-scheduling [...]". Вы можете увидеть это, включив ведение журнала трассировки на org.hibernate.event.internal.DefaultPersistEventListener
регистратор.
Если это ситуация, вам нужно будет очистить эти ассоциации, как требуется JPA спецификация.
замена cascade = CascadeType.ALL
by orphanRemoval = true
на @OneToMany
ассоциация дает ожидаемый результат: дочерние записи правильно удаляются без необходимости удаления родительской записи.
жаль, что ошибка не регистрируется более четко.
Я получил ту же проблему, когда следующие вещи собрались вместе.
- спящий режим 3.6.10.Финал
- родительский объект с нет ссылка на ребенка.
-
некоторая дочерняя сущность со ссылкой на родителя. Это устаревший код.
class ChildEntity { @ManyToOne(cascade = CascadeType.ALL) private ParentEntity parent; }
дочерняя сущность загружается в контекст сеанса, а затем удаляется из таблицы без уведомления JPA в транзакции (хранимая процедура, собственный в SQL)
затем родитель не может быть удален. Нет удаления, нет исключения, просто сообщение "не запланировать удаление" в журнале трассировки.
решение: я удалил атрибут каскада. Мне было немного сложно найти, какой дочерний объект блокирует родительское удаление. Кроме того, я не понимаю, почему Дочерний каскад влияет, если я удаляю родительский объект.