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 ассоциация дает ожидаемый результат: дочерние записи правильно удаляются без необходимости удаления родительской записи.

жаль, что ошибка не регистрируется более четко.


Я получил ту же проблему, когда следующие вещи собрались вместе.

  1. спящий режим 3.6.10.Финал
  2. родительский объект с нет ссылка на ребенка.
  3. некоторая дочерняя сущность со ссылкой на родителя. Это устаревший код.

    class ChildEntity {
      @ManyToOne(cascade = CascadeType.ALL)
      private ParentEntity parent;
    }
    
  4. дочерняя сущность загружается в контекст сеанса, а затем удаляется из таблицы без уведомления JPA в транзакции (хранимая процедура, собственный в SQL)

  5. затем родитель не может быть удален. Нет удаления, нет исключения, просто сообщение "не запланировать удаление" в журнале трассировки.

решение: я удалил атрибут каскада. Мне было немного сложно найти, какой дочерний объект блокирует родительское удаление. Кроме того, я не понимаю, почему Дочерний каскад влияет, если я удаляю родительский объект.