Подтвердить что ты не робот

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 выполняет несколько запросов выбора, но даже не пытается выполнить удаление.

Я уже пробовал предложения, найденные в других подобных вопросах здесь и здесь, но безрезультатно (ну, последнее предлагает @Transactional, который я не могу использовать, но я просто заключил в себе выражения между begin() и commit()).

Я не могу найти, что эти два класса имеют больше (или меньше), чем другие. Они используют @PrimaryKeyJoinColumn так же, как и почти все другие объекты, которые у меня есть, они имеют @OneToMany и @ManyToOne точно так же, как ohters. Честно говоря, у них есть поле @OneToOne(optional = false), которое ссылается на другой класс, а другие объекты не имеют, но я бы не стал обсуждать проблему изменения этого (и, следовательно, изменения схемы базы данных), если вы не скажете мне, что можно быть причиной для этого.

Является ли @OneToOne ответственным? Или мой код удаления прослушивается?

4b9b3361

Ответ 1

Есть ли у вас ассоциации на этом графике, которые каскадно сохраняют обратно к удаляемой вещи? Если это так, спецификация JPA четко указывает, что провайдер должен отменить удаление в таком случае. Если это так, Hibernate выписывает выражение журнала, в котором говорится: "Отмена удаления объекта [...]". Это можно увидеть, включив ведение журнала трассировки в журнале org.hibernate.event.internal.DefaultPersistEventListener.

Если это так, вам нужно очистить эти ассоциации, как того требует спецификация JPA.

Ответ 2

Замена cascade = CascadeType.ALL на orphanRemoval = true в ассоциации @OneToMany дает ожидаемый результат: дочерние записи удаляются без необходимости удаления родительской записи.

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

Ответ 3

У меня возникла такая же проблема, когда мы собрали все вместе.

  • Hibernate 3.6.10.Final
  • Родительский объект с no ссылкой на Child.
  • Некоторые дочерние объекты со ссылкой на родителя. Это устаревший код.

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

  • Затем родительский элемент нельзя удалить. Отсутствие исключения, исключение, просто сообщение "расписание удаления" в журнале TRACE.

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

Ответ 4

Помимо всего этого, если у вас уже есть правильные значения каскадных и сиротских значений, в моем случае я обнаружил еще одну причину, по которой УДАЛЕНИЕ не может быть выполнено, даже если все выглядит нормально и даже когда УДАЛЕНО находятся в журнале, но база данных не показывает никаких изменений.,

Это также может быть транзакционной проблемой, но в моем случае это было то, что ключ (в Oracle Database) в запросе на удаление имел тип данных CHAR (8) в базе данных, в этом случае, как вы можете найти в документации Oracle CHAR по сравнению с VARCHAR2, если ваши данные не имеют длины 8, остальные покрыты пробелом, а в JPA DELETE делается различие между "0001" и "0001".

Я пишу этот ответ, потому что я не вижу ничего подобного во всех моих исследованиях, и кто-то еще мог пройти через этот пост и иметь ту же проблему.

Приветствия.

Ответ 5

У меня была такая же проблема с сущностью, которая имеет много отношений. Что я сделал, так это установил обнуление родительских сущностей, произвел слияние, затем сделал сброс и очистку и, наконец, получил сущность снова, используя find и remove. Например:

objAgreement.setParent(null);
em.merge(objAgreement);
em.flush();
em.clear();

objAgreement= em.find(Agreement.class, objAgreement.getId())
em.remove(objAgreement);