Hibernate: проверить нарушение ограничения внешнего ключа перед удалением? - PullRequest
4 голосов
/ 28 февраля 2012

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

Итак, в основном я пытался определить, присутствует ли ключ объекта в другой таблице. Если это не так, я бы просто вызвал 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» операции, в которой я мог бы проверить, не удалится ли удаление из-за ограничения, без фактического выполнения операции (и, таким образом, аннулирования сеанса). Единственное, о чем я могу подумать, - это вручную проверить каждую связанную таблицу, чтобы увидеть, присутствует ли идентификатор, но это будет очень утомительно и подвержено ошибкам в таблицах со многими взаимосвязями. Я хочу использовать ограничения, которые уже существуют в базе данных, если это возможно.

1 Ответ

0 голосов
/ 28 февраля 2012

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

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

и:

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

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

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

Обновление:

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

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

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

...