Hibernate - Мне действительно нужно откатить транзакцию только для чтения?

Я только начал изучать Hibernate, и я использую следующий шаблон (из документация) для каждой транзакции:

private Session session;
private Transaction transaction;

protected List selectAll(Class clazz) throws HibernateException {
    List objects = null;
    try {
        session = MyHibernateHelper.getSessionFactory().openSession();
        transaction = session.beginTransaction();

        // SELECT ALL
        objects = session.createCriteria(clazz).list();

        transaction.commit();
    } catch (HibernateException exc) {
        if (transaction != null) transaction.rollback();
        throw exc;
    } finally {
        session.close();
    }
    return objects;
}

Я могу согласиться с тем, что каждая операция должна быть заключена в транзакцию. Но мне кажется странным и ненужным откат select, если он не сработает.
Я думаю, что я могу безопасно удалить блок catch из приведенного выше примера. И из любой операции только для чтения. Я прав?

Ответ 1

Рассмотрим, что Hibernate должен работать со всеми типами баз данных для всех ситуаций. Их документация заключается в том, как использовать Hibernate из любой поддерживаемой базы данных. И они пытаются поддерживать множество баз данных. Некоторые из этих баз данных могут обрабатывать неудачные транзакции, не требуя явного отката, но Hibernate хочет удостовериться, что он охватывает всех.

Также подумайте о том, что сбой транзакции только для чтения будет крайне редок в реальной жизни. Как только это произойдет, для отката не будет многого, но то, что он делает - освобождение блокировок, как указывает Марк Б, - это не то, что вы хотите пропустить. Так что вы защищаете, это очень крошечная оптимизация (основанная на том, как редко этот путь тренируется), что может иметь плохие последствия в некоторых обстоятельствах. Наличие блокировки не освобождается, это плохое следствие, которое не проявляется до тех пор, пока какая-либо другая транзакция не сработает или не повесится, что очень затрудняет отслеживание причины. Блокировка, которая не будет выпущена, может стать причиной блокировки, поэтому воздействие производительности/доступности может быть ужасным. Также это было бы болью для проверки, если есть проблема, ее можно было бы упустить, пока не возникнет кризис в производственной среде. По многочисленным подсчетам это то, чего вы хотите избежать.

Самая большая проблема здесь заключается в том, что для каждой транзакции необходимо включить код шаблона. Мое предложение состоит в том, чтобы либо реализовать некоторые методы утилиты, используя обратные вызовы, либо шаблон команды (см. Примеры Bauer и King Book Java Persistence with Hibernate для примеров), либо принять структуру. Существует аргумент против фреймворков, что они скрывают детали реализации и усложняют обучение, но у вас уже есть опыт изучения того, как эти части объединены. Существуют зрелые структуры, такие как Seam или Spring который будет обрабатывать это для вас.

Ответ 2

Если вы используете фреймворк или API или что на самом деле не находится под вашим контролем, вы всегда должны уважать их стратегию отказа, потому что вы не знаете, как это работает на внутреннем уровне. Возможно, есть другие ресурсы для бесплатного использования.