Для більш детального опису ви можете прочитати мою статтю " Відкрита сесія" у "Перегляд протизразка" . В іншому випадку, ось короткий опис того, чому не слід використовувати Open Session In View.
Відкрита сесія в режимі перегляду погано підходить до отримання даних. Замість того, щоб дозволити бізнес-шару вирішувати, як найкраще отримати всі асоціації, необхідні шару «Перегляд», він змушує Контекст стійкості залишатися відкритим, щоб шар Перегляд може спровокувати ініціалізацію проксі.
OpenSessionInViewFilter
Викликає openSession
метод базового активу SessionFactory
і отримує новий Session
.
Session
Пов'язаний з TransactionSynchronizationManager
.
OpenSessionInViewFilter
Називає doFilter
в якості javax.servlet.FilterChain
посилання об'єкта і запит додатково обробляється
DispatcherServlet
Називається, і він направляє запит HTTP , щоб лежачий в основі PostController
.
- У
PostController
дзвінки на , PostService
щоб отримати список Post
сутностей.
PostService
Відкриває нову транзакцію, і HibernateTransactionManager
повторно той же , Session
що був відкритий OpenSessionInViewFilter
.
PostDAO
Отримує список Post
осіб без ініціалізації будь ледачою асоціації.
PostService
Здійснює основну угоду, але Session
не закритий , так як він був відкритий зовні.
- У
DispatcherServlet
запуску рендеринга інтерфейсу, який, в свою чергу, переходить ледачі асоціації і викликає їх ініціалізації.
- Can
OpenSessionInViewFilter
може закрити Session
, і базове з'єднання бази даних також вивільнено.
На перший погляд, це може не виглядати як жахлива річ, але, коли ви переглядаєте це з точки зору бази даних, ряд недоліків починає ставати більш очевидним.
Сервісний рівень відкривається та закриває транзакцію бази даних, але після цього явної транзакції не відбувається. З цієї причини кожна додаткова заява, видана на етапі візуалізації користувальницького інтерфейсу, виконується в режимі автоматичної фіксації. Функція автоматичного фіксації чинить тиск на сервер бази даних, оскільки кожне твердження повинно передати журнал транзакцій на диск, тому спричиняючи багато трафіку вводу / виводу на стороні бази даних. Однією з оптимізацій було б позначити Connection
як лише для читання, що дозволить серверу баз даних уникати запису в журнал транзакцій.
Більше проблем не існує, оскільки заяви створюються як службовим рівнем, так і процесом надання інтерфейсу користувача. Для написання тестів на інтеграцію, що підтверджують кількість генерованих висловлювань, потрібно пройти всі шари (веб, сервіс, DAO), при цьому додаток буде розміщено у веб-контейнері. Навіть при використанні бази даних в пам'яті (наприклад, HSQLDB) та легкого веб-сервера (наприклад, Jetty), ці інтеграційні тести виконуватимуться повільніше, ніж якщо б шари були розділені і тести інтеграції заднім числом використовували базу даних, тоді як фронтальні тести інтеграції взагалі глузували з сервісного рівня.
Шар інтерфейсу обмежений навігаційними асоціаціями, які, в свою чергу, можуть викликати проблеми запитів N + 1. Незважаючи на те, що Hibernate пропонує @BatchSize
пакетні асоціації для отримання пакетів і FetchMode.SUBSELECT
для вирішення цього сценарію, примітки впливають на план вибору за замовчуванням, тому вони застосовуються до кожного випадку використання бізнесу. З цієї причини запит рівня доступу до даних набагато підходить, оскільки він може бути налаштований під поточні вимоги використання даних щодо поточного використання.
І останнє, але не менш важливе, підключення до бази даних може відбуватися протягом усієї фази візуалізації інтерфейсу (залежно від режиму випуску з'єднання), що збільшує час оренди з'єднання та обмежує загальну пропускну здатність транзакцій через перевантаженість пулу підключення до бази даних. Чим більше з'єднання проведено, тим більше інших одночасних запитів буде чекати, щоб отримати з'єднання з пулу.
Таким чином, або ви тримаєте з'єднання занадто довго, або ви отримуєте / випускаєте кілька з'єднань для одного HTTP-запиту, тому тиснуть на базовий пул з'єднань і обмежуючи масштабованість.
Весняний черевик
На жаль, Open Session in View увімкнено у Spring Boot за замовчуванням .
Отже, переконайтеся, що у application.properties
файлі конфігурації є такий запис:
spring.jpa.open-in-view=false
Це відключить OSIV, щоб ви могли правильно впоратисяLazyInitializationException
.