2012-02-28 1 views
3

В системе, в которой я сейчас работает, есть политика, в которой объекты, не имеющие отношения, могут быть свободно удалены, а те, которые должны быть выполнены, должны быть логически удалены. Это предназначено для предотвращения удаления исторической информации.Hibernate: проверить нарушение ограничения внешнего ключа перед удалением?

Так что в основном то, что я пытался сделать, это определить, присутствует ли в данный момент ключ объекта в другой таблице. Если это не так, я бы просто вызвал delete(), иначе я бы установил свойство, которое указывает на логическое удаление, и вызовет update().

Я использую управление транзакциями Spring, поэтому я стараюсь как можно меньше связываться с сеансом. Мой первоначальный подход, казалось, работал на первом, но вы увидите, что она имеет большой недостаток:

@Transactional 
public void deleteObject(SomeEntity object) 
{  
    //try to delete 
    this.someEntityDAO.delete(object); 

    try //force foreign key constraint check 
    { 
     this.someEntityDAO.flush(); 
    } 
    catch (ConstraintViolationException e) 
    { 
     //reload object 
     object= this.someEntityDAO.loadById(object.getId()); 

     //save as inactive instead of deleting 
     object.setActive(false); 
     this.someEntityDAO.update(object); 
    } 
} 

Поскольку Hibernate исключение является фатальным, это совершенно ненадежно (даже если он работает). Мне было интересно, есть ли способ сделать какую-то операцию «peek», в которой я мог бы проверить, не удастся ли удалить из-за ограничения, фактически не выполнив операцию (и тем самым аннулирует сеанс). Единственное, о чем я могу думать, это вручную проверить каждую связанную таблицу, чтобы увидеть, присутствует ли идентификатор, но это было бы очень утомительно и подвержено ошибкам в таблицах со многими отношениями. Я хочу использовать ограничения, которые уже существуют в базе данных, если это возможно.

ответ

0

Говоря конкретно:

Поэтому в основном то, что я пытался сделать, это определить, является ли ключ объекта в настоящее время присутствует в другой таблице. Если это не так, я бы просто вызвал delete(), иначе я бы установил свойство, которое указывает на логическое удаление, и вызовет update().

и:

мне было интересно, если есть способ сделать своего рода «прятки» операции, в которой я мог бы проверить, если удаление потерпит неудачу из-за ограничений, без фактического выполнения (и тем самым аннулирует сеанс).

Я работал только с Hibernate, но общий ответ: для этого нужен SQL. Это все в твоем месте!

Для наглядности: вы делаете свое удаление с достаточным предложением where, которое оно выполняет в самой транзакции; Удаление удаляет все, что соответствует заданным ограничениям.

Update:

Когда вы пишете:

«Поэтому в основном то, что я пытался сделать, это определить, есть ли в настоящее время в другой таблице ключ объекта Если это не так. Я бы просто вызвал delete(), иначе я бы установил свойство, которое указывает на логическое удаление, и вызовет update(). "

проблема заключается в том, что вы пытаетесь сделать это, когда вы должны позволить (направлять) механизм базы данных, чтобы сделать это для вас в вашем SQL. Исследуйте использование предложения «не существует» ...

+0

Да, я могу сделать это с помощью SQl напрямую или добавить дополнительный код Hibernate для проверки этих ограничений перед удалением.Дело в том, что я не хотел так поступать, так как тогда мне пришлось бы отслеживать все отношения между сущностями и вернуться к коду, если бы было добавлено больше отношений и т. Д. Если бы я был в порядке для этого, как я и предложил, мне просто нужно было бы правильно установить ограничения в БД и никогда не вернуться к этому коду еще раз, независимо от того, изменилась ли база данных в какой-то момент или нет. – JayPea

+0

@JayPea «Если бы у меня был способ сделать это, как я предложил, мне просто нужно было бы правильно установить ограничения на БД и никогда не вернуться к этому коду еще раз, независимо от того, изменилась ли база данных в какой-то момент или нет. " Предполагая, что вы НЕ означает, что изменится база данных DESIGN, тогда ДА, вы МОЖЕТЕ это сделать! И должен. ... Референтная целостность - вещь VITAL; научиться этому, использовать его, позволить ему расширить свою работу! (BTW, я работаю с Postgres, Informix, Ingres, Oracle, DB2, Sybase, среди прочих - все серьезные реляционные системы баз данных имеют встроенные функции). –

 Смежные вопросы

  • Нет связанных вопросов^_^