Хотя было написано много постов по теме OpenSession / EntityManagerInViewFilter от Spring, я не смог найти ни одного, в котором упоминались бы его недостатки. Из того, что я понимаю, и исходя из типичной многоуровневой архитектуры веб-приложений с использованием сервисного уровня @Transactional, фильтр работает следующим образом:
- Фильтр перехватывает запрос сервлета
- Фильтр открывает EntityManager и привязывает его к текущему потоку
- Веб-контроллер называется
- Веб-контроллер вызывает службу
- Перехватчик транзакции начинает новую транзакцию, получает связанный с потоком EntityManager и связывает его с транзакцией
- Служба вызывается, что-то делает с EntityManager, затем возвращает
- Перехватчик транзакций сбрасывает EntityManager, а затем фиксирует транзакцию
- Веб-контроллер готовит представление, затем возвращает
- Вид построен
- Фильтр закрывает EntityManager и отсоединяет его от текущего потока
На шагах 8 и 9 объекты, которые были загружены EntityManager потока, по-прежнему управляются. Следовательно, если на этих этапах затрагиваются ленивые ассоциации, они будут загружены из базы данных с помощью все еще открытого EntityManager. Из того, что я понимаю, каждый такой доступ потребует, чтобы база данных открыла транзакцию. Управление транзакциями Spring не будет знать об этом, поэтому я назвал это «неявной транзакцией».
Я вижу 2 проблемы с этим:
- Загрузка нескольких ленивых ассоциаций приведет к нескольким транзакциям базы данных, что может снизить производительность
- Корневой объект и его ленивые ассоциации загружаются в разные транзакции базы данных, поэтому данные могут быть устаревшими (например, корень загружен потоком 1, корневые ассоциации обновлены потоком 2, корневые ассоциации загружены потоком 1)
С одной стороны, этих двух проблем, по-видимому, достаточно, чтобы отказаться от использования этого фильтра (снижение производительности, несогласованность данных). С другой стороны, это решение очень удобно, позволяет избежать написания нескольких строк кода, проблема 1 может быть не такой заметной, а проблема 2 - чистой паранойей.
Что вы думаете?
Спасибо!