#java #hibernate #java_ee #шаблоны_проектирования #java_8
В одной статье по Hibernate прочитал, что если вы хотите использовать многопоточность, то создавайте новую сессию для каждой CRUD-операции. То есть вот как выглядит, например, операция сохранения в моем DAO-классе: public void save(User user) { try (Session session = HibernateSessionFactoryUtil.getSessionFactory().openSession()) { Transaction tx = session.beginTransaction(); session.save(user); tx.commit(); } } Но вот незадача. Сегодня наткнулся на еще одну статью, в которой говорят, что описанное выше действие является анти-паттерном. Дословно: Это анти-паттерн про открытие и закрытие объекта Session на каждую операцию к БД в одном потоке. Это также анти-паттерн в терминах транзакций БД. Группируйте ваши вызовы в одну запланированную последовательность. Также, не делайте авто-коммит транзакции на каждое SQL-выражение. Hibernate выключает, или ожидает, что сервер приложений немедленно выключит режим авто-коммита. Заместо этого в этой статье предложен Паттерн сессия-на-запрос, где его описывают как: Наиболее распространенный паттерн транзакций. Термин “запрос” здесь следует понимать в контексте системы, реагирующей на серии запросов от пользователя/клиента. Веб-приложения является основным примером таких систем, но, конечно, не только они одни. На этапе начала обработки запроса, приложение открывает объект Session, инициирует транзакцию, проводит всю сопутствующую работу с данными, завершает транзакцию и закрывает Session. Суть паттерна – это отношение один-к-одному между транзакцией и сессией. После этого у меня возник когнитивный диссонанс. Во-первых потому, что оказывается согласно этой статье, раньше я делал не так, создавая сессию для каждой операции, а во-вторых потому, что я не понял, что предполагает второй паттерн. Объясните, что из этого правда, а что ложь? Что использовать, а про что забыть?
Ответы
Ответ 1
Если обратится к документации Hibernate - то по ней сессия-на-операцию официально обьявлена антипаттерном. Что касается сессии, то сам ее смысл предполагает что вы можете и по возможности должны объединять связанные по смыслу операции в рамках одной или нескольких транзакций в одну сессию. В тоже время ничего плохого нет в том что ваша сессия может содержать лишь одну операцию, если кроме этой операции ничего делать не надо. Чтобы понять разницу между первым и вторым приведу пример: представьте что существует еще один класс связанный с User, например UserHistory (пусть он будет хранить историю изменения имени пользователя). Мы предполагаем по смыслу что изменяя name в User должен обязательно обновляться и класс UserHistory. Теперь представим что мы сделали все через operation-per-session. В этом случае у нас будет две разные сессии и две транзакции которые обновят User и UserHistory независимо друг от друга. Проблема возникнет тогда когда одна из транзакций не дойдет (например из за внезапных потерь на сети) что неизбежно приведет к нарушению целостности данных в БД. И да, при работе с БД не через пулы - крайне ресурсоемко создавать и закрывать соединения с БД при каждом действии.Ответ 2
Действительно как пишется в документации к Hibernate: The scope of a Hibernate org.hibernate.Session is flexible but you should never design your application to use a new Hibernate org.hibernate.Session for every database operation. Even though it is used in the following examples, consider session-per-operation an anti-pattern Обратите внимание, что говорится о новой сессии, по сути предлагается использовать текущую сессию, а именно: Session session = HibernateUtil.getSessionFactory().getCurrentSession(); session.beginTransaction(); //blah-blah session.getTransaction().commit(); То есть если нет текущей сессии, то создаем, если есть берем текущую. Создание сессии при каждой операции является антипаттерном, но не потому, что типа в другой сессии будет произведено обновление или там не дойдет до конца транзакция (менеджер транзакций СУБД вполне умеет с такими вещами работать), а из-за стоимости создания сессии - по сути это новый коннект к БД - крайне дорогая и ресурсоемкая операция.
Комментариев нет:
Отправить комментарий