Подтвердить что ты не робот

Spring Загрузка и Spring Данные: как выполняются сеансы Hibernate?

В настоящее время я работаю над приложением, которое использует Spring Boot и Spring Data (его JpaRepository интерфейсы, чтобы быть точным) вместе с Hibernate.

Одна вещь, которую я люблю в Hiberante, - это ее функция кеширования - когда вы отправляете несколько запросов, которые соответствуют определенному объекту, вы получите тот же экземпляр этого объекта при каждом выполнении запроса (относительно оператора Java ==). Однако при использовании классов Spring Data и JpaRepository это не всегда так. По этой причине я предполагаю, что здесь есть несколько экземпляров HibernateSession.

Мой вопрос заключается в следующем: как Spring Data обрабатывает сеансы Hibernate? Когда он открывает или закрывает их? Есть ли способ настроить его на использование одного и того же сеанса для всей среды выполнения моего приложения, чтобы в полной мере использовать кеш-память Hibernate? Есть ли причина не делать этого таким образом?

Спасибо,

Алан

4b9b3361

Ответ 1

Я думаю, что нашел ответ сам. Если кто-то найдет этот вопрос, вот мой ответ.

Как Spring управляет сессиями Hibernate?

По умолчанию Spring Boot применяет управление транзакциями на уровне хранилища. В этом случае при вызове метода JpaRepository (или вообще любого метода Repository) Spring будет:

  • Попросите SessionFactory создать новую сессию
  • Откройте эту сессию
  • Открыть транзакцию
  • Выполните вызванный метод Repository
  • Закрыть транзакцию
  • Закройте сессию

Однако если вы примените @Transactional к классу или методу сервиса, Spring откроет сеанс и транзакцию при входе в метод сервиса, а метод репозитория будет выполнен в рамках существующей транзакции.

Каковы последствия?

Как программист...

  • Вам вообще не нужно заниматься транзакциями или сеансами.
  • если вы хотите полагаться на функциональность кэширования Hibernate, вы должны указать @Transactional в большем объеме, чем хранилище. Кэширование работает только в пределах одной и той же HibernateSession.
  • вы должны решить эквивалентность ваших объектов @Entity по их значению Hibernate ID, а не с помощью оператора Java ==.
  • вам нужно позаботиться о том, чтобы ленивые коллекции (например, в ссылке @OneToMany) в ваших классах @Entity (см. FetchMode.LAZY в отличие от FetchMode.EAGER) использовались исключительно в @Transactional -annotated

Также для справки была бы полезна следующая ссылка: несколько транзакций в одном сеансе

Как и во многих других аспектах Spring, здесь многое можно получить, если вы готовы пожертвовать прямым контролем над своим приложением.