Що це за Spring.jpa.open-in-view = справжня властивість у Spring Boot?


121

Я бачив spring.jpa.open-in-view=trueвластивість у документації Spring Boot для конфігурації JPA.

  • Чи є trueзначенням цього властивості за замовчуванням, якщо він взагалі не надається ?;
  • Що це насправді робить? Я не знайшов жодного хорошого пояснення для цього;
  • Це змушує вас використовувати SessionFactoryзамість EntityManagerFactory? Якщо так, то як я можу сказати це, щоб дозволити мені використовувати EntityManagerFactoryзамість цього?

Дякую!

Відповіді:


52

У цьому властивості буде зареєстровано an OpenEntityManagerInViewInterceptor, який реєструє a EntityManagerдо поточного потоку, тому у вас буде те саме, EntityManagerпоки веб-запит не буде закінчений. Це не має нічого спільного із сплячим режимом SessionFactoryтощо.


На даний момент у мене є фільтр OpenEntityManagerInViewFilter для управління EntityManager до завершення веб-запиту. Цей перехоплювач, який ви мали на увазі "OpenEntityManagerInViewInterceptor" - це те саме, що "OpenEntityManagerInViewFilter"? Яка різниця між ними? Отже, я б не мав більше цього фільтра в контексті сервлету для Spring Boot?
Карлос Альберто

1
Перехоплювач працює лише тоді, коли ви використовуєте DispatcherServlet навесні (оскільки перехоплювач є механізмом Spring). Фільтр можна відобразити на всіх налаштованих сервлетах (ми використовуємо його для FacesServlet в одному з наших додатків). Отже, якщо ви використовуєте лише DispatcherServlet, ви можете додати властивість та видалити фільтр, інакше використовуйте фільтр.
dunni

299

Антидіаграма OSIV

Замість того, щоб дозволити бізнес-шару вирішувати, як найкраще отримати всі асоціації, необхідні шару «Перегляд», OSIV (Open Session in View) змушує контент контексту залишатися відкритим, щоб шар 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щоб впоратися з цим сценарієм, примітки впливають на план вибору за замовчуванням, тому вони застосовуються до кожного випадку використання бізнесу. З цієї причини запит рівня доступу до даних набагато підходить, оскільки він може бути адаптований до поточних вимог використання даних щодо використання випадку.

І останнє, але не менш важливе, підключення до бази даних проводиться протягом усієї фази візуалізації інтерфейсу, що збільшує час оренди з'єднання та обмежує загальну пропускну здатність транзакцій через перевантаженість пулу підключення до бази даних. Чим більше з'єднання проведено, тим більше інших одночасних запитів буде чекати, щоб отримати з'єднання з пулу.

Весняне завантаження та OSIV

На жаль, OSIV (Open Session in View) включено за замовчуванням у Spring Boot , а OSIV - це дійсно погана ідея з точки зору продуктивності та масштабованості .

Отже, переконайтеся, що у application.propertiesфайлі конфігурації є такий запис:

spring.jpa.open-in-view=false

Це відключить OSIV, щоб ви могли правильно впоратисяLazyInitializationException .

Починаючи з версії 2.0, Spring Boot видає попередження, коли OSIV увімкнено за замовчуванням, тому ви можете виявити цю проблему задовго до того, як вона вплине на виробничу систему.

Щоб отримати докладнішу інформацію про OSIV, перегляньте цю статтю .


14
Наразі реєструється ПОПЕРЕДЖЕННЯ.
Влад Міхалча

Це стосується Spring взагалі чи лише Spring Boot? Чи можна це відключити за допомогою класу @ @ Configuration-annotated замість встановлення властивості?
Гордон

2
Це стосується лише весняного завантаження. У стандартному режимі Spring ви чітко вибираєте, яку квасолю використовувати або хочете веб-фільтр, як OSIV. Я не знаю, чи можна вимкнути це за допомогою анотації. Я знаю лише налаштування конфігурації.
Влад

Це не анти-модель. Це має вплив на ефективність, іноді негативний, багато разів досить нейтральний, а в багатьох випадках позитивний: якщо ви хочете почати ліниве відношення, вам не потрібно робити запит у всіх випадках і може уникнути цього, коли потрібно, використовуючи відкритий перегляд.
ymajoros

5
За даними Вікіпедії, "антидіаграма - це звичайна відповідь на повторювану проблему, яка, як правило, неефективна і ризикує бути дуже контрпродуктивною". Саме це і є Open Session in View.
Влад Михальча
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.