Проверка существования объекта перед удалением или обновлением в Spring / Hibernate - PullRequest
5 голосов
/ 07 мая 2011

Я использую для своего проекта комбинацию Spring / Hibernate со стандартными операциями CRUD.

Интересно, разумно ли проверять существование объекта перед его удалением или обновлением? Если это так, где наиболее подходящее место - сервис или слой дао?

EDIT:
Извините, я не сразу понял, когда задал этот вопрос. Единственный мотив для проверки существования - бросить дружественное исключение клиенту службы (без DAO).

Проблема в том, что я «должен» выполнить проверку существования, потому что мой метод обслуживания ниже транзакционный, и, кроме того, я использую вспомогательные классы HibernateTemplate и DaoSupport для манипулирования сеансами в объектах DAO.

В соответствии с упомянутым выше, исключение Hibernate (например, в случае удаления несуществующего экземпляра) генерируется во время принятия, что вне моей досягаемости, потому что (я полагаю) принятие выполняется PlatformTransactionManager в прокси-объекте, и я у меня нет возможности обработать это исключение в моем методе обслуживания и повторно выдать дружественное исключение клиенту.

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

Например:

//Existence checking in this example is not so important
public void delete(Employee emp){  
    Employee tempEmp=employeeDao.read(emp.getId());  
    if(tempEmp==null)  
        throw new SomeAppSpecificException();  
}  
//Existence checking in this example is maybe 'more logical'    
public void save(Assignment a){  
    Task t=taskDao.read(a.getTask().getId());
    if(t==null)  
        throw new FriendlyForeignKeyConstraintException(); 
    Employee e=employeeDao.read(a.getEmployee().getId());  
    if(e==null)  
        throw new EmployeeNotFoundExc();
    //...some more integrity checking and similar...  
    assignmentDao.save(a); 
}

Дело в том, что я просто хочу вывести дружественное исключение с соответствующим сообщением в случае упомянутых ситуаций (нарушения целостности и тому подобное).

1 Ответ

3 голосов
/ 12 мая 2011

В терминах Hibernate операции обновления и удаления (и соответствующие методы в Session ) имеют дело с постоянными сущностями.Следовательно, их существование подразумевается, и проверять его снова в вашем коде бессмысленно - Hibernate сделает это самостоятельно и выдаст исключение, если это не так.Затем вы можете перехватить и обработать (или перебросить) это исключение.

В примечании (на основе вашего примера кода) нет необходимости явно читать экземпляр, который вы собираетесь удалить.Session предоставляет метод load () , который будет возвращать экземпляр прокси-сервера, подходящий для передачи в метод delete() без фактического попадания в базу данных.Предполагается, что экземпляр, связанный с данным PK, существует и завершится с ошибкой (сгенерирует исключение) позже, если это не так.

Редактировать (на основе разъяснения вопроса):

Когда вы говорите, что хотите бросить «дружественное» исключение клиенту, определения «дружественный» и «клиент» становятся важными.В большинстве реальных сценариев ваша транзакция будет охватывать более чем простой атомарный метод «save ()» или «delete ()» в одной из ваших служб.

Если клиент локальный, а вы - нетнеобходимы отдельные транзакции в рамках одного взаимодействия с клиентом (типичный сценарий - веб-приложение, работающее на одной виртуальной машине с уровнем обслуживания), обычно рекомендуется инициировать / фиксировать транзакцию там (см., например, Open Session In View ).Затем вы можете поймать и должным образом обработать (включая упаковку / перебрасывание, если необходимо) исключения во время фиксации.Другие сценарии являются более сложными, но в конечном итоге исключение будет распространено на ваш клиент «верхнего уровня»;просто разворачивание может оказаться сложным, если вам нужно представить клиенту «основную» причину «дружественным» способом.

Суть в том, что дело за вами.Если вы предпочитаете быстро потерпеть неудачу за собственным исключением (за счет написания некоторого стандартного кода), в этом нет ничего плохого.

...