#java #hibernate #exception
#java #гибернация #исключение
Вопрос:
Мой работник базы данных реализован над режимом гибернации. Если что-то пойдет не так, его методы должны откатить транзакцию и выдать SQLException
. Итак, мой вопрос: каков наилучший (т. Е. Самый чистый) способ обработки исключений гибернации? В настоящее время все мои методы выглядят так же уродливо, как это:
public EntryUserHib addUser(final String username, final String pwdhash) throws SQLException{
try {
final Transaction ta = sess.beginTransaction();
try {
// Using Hibernate here
// "return" statement
} catch(final HibernateException ex) {
try {
ta.rollback();
} catch(final Exception ex1) {}
throw ex;
} finally {
if (!ta.wasRolledBack()) ta.commit();
}
} catch(final HibernateException ex) {
if (ex.getCause() != null) {
if (ex.getCause() instanceof SQLException) throw (SQLException)ex.getCause();
throw new SQLException(ex.getCause());
}
throw new SQLException(ex);
}
}
Ответ №1:
Не перехватывайте их вообще. Исключения гибернации расширяют исключение RuntimeException по двум веским причинам: вам не нужно объявлять их в сигнатурах методов, и любое исключение RuntimeException автоматически вызывает откат транзакции. Обработка исключений приводит к очень загроможденному коду. У сотрудников Hibernate есть философия, согласно которой исключения HibernateExceptions должны быть фатальными ошибками, сигнализирующими о кодировании или логических ошибках, и в правильно функционирующем приложении не должны быть (и не должны быть) перехвачены.
Однако пользовательский интерфейс вашего приложения должен реагировать на эти сюрпризы удобным для пользователя способом. Это отдельная проблема.
Комментарии:
1. Это серверное приложение без пользовательского интерфейса и множества выполняемых параллельных задач, и ни одна из них не должна наносить вред всему приложению, поэтому мне действительно нужно их перехватывать и повторно выбрасывать объявленным способом. Другой причиной этого является тот факт, что существует три реализации my
DatabaseWorker
— использование Hibernate, JDBC и simple in-memory model для тестов, и в настоящее время я могу свободно переключать их.2. Исключение HibernateException включает в себя множество других исключений, включая исключение SQLException, это может быть сбой сети, не обязательно кодирование или логика, может быть или не быть фатальным в зависимости от вашего приложения. В ситуации с сервером обычно нет ничего «фатального» в отношении исключения HibernateException, оно обычно должно быть перехвачено и удалено, и сервер должен продолжить.
Ответ №2:
Пусть кто-то другой управляет этим за вас, например Spring. Он имеет обширную поддержку гибернации и транзакций, которая извлекает весь тот код, о котором вы беспокоитесь.
Комментарии:
1. Спасибо, я посмотрю на это, но действительно ли мне нужно использовать фреймворк только для управления исключениями одного класса?
2. Распространенное заблуждение, что Spring — это «всего лишь» фреймворк. В него упакованы тонны повторно используемых библиотек. Например, для вашей ситуации он предлагает TransactionTemplate и HibernateTemplate (как указано ранее), которые делают именно то, что вы просите. Да, вы могли бы написать их самостоятельно, но зачем?