Хранение открытого JPA EntityManager?

Я изучаю JPA, и общий шаблон в примерах, кажется, следующим образом:

EntityManager em = factory.createEntityManager();
em.getTransaction().begin();
// ....
em.getTransaction().commit();
em.close();

Теперь я задаюсь вопросом, почему мы постоянно создаем и закрываем EntityManagers, в противоположность хранению его открываются и просто запуск новых транзакций? Каковы преимущества и затраты на хранение, оно открывает по сравнению с закрытием всего этого время?

14
задан Pascal Thivent 17 August 2010 в 05:24
поделиться

2 ответа

На ум приходят две специфические для JPA причины:

  1. EntityManager не гарантированно потокобезопасен спецификацией JPA. Поэтому переносимые приложения JPA могут использовать EM не более чем в одном потоке одновременно. Идиома создания локального EM в методе и его закрытия до того, как он выйдет из области видимости, способствует ограничению стека ссылок на EM.

  2. EM, использующий "расширенный" Persistence Context Lifetime, сохраняет один контекст персистентности на протяжении всего своего существования. Это означает, что сущности перестают автоматически отделяться при commit(). Вместо этого они должны быть отсоединены вручную, иначе EM остается ответственным за их отслеживание.

Этот вопрос на самом деле является специфичной для JPA версией старого вопроса "когда объединять объекты в пул". Это сложный вопрос, но ответ, вероятно, "редко".

Это старое сообщение на developerWorks эксперта по параллелизму Java Брайана Гетца объясняет суть вопроса. Суть: пулы имеют большой смысл для дорогостоящих объектов, таких как соединения с базой данных. Но для недолговечных, небольших и быстро инициализируемых объектов, таких как EntityManager, объединение в пулы или какая-либо другая форма долгосрочного хранения ссылок является трудновыполнимой задачей.

Но это общий вопрос, поэтому обязательно будут исключения. Может быть, приложение простое или однопоточное. Тогда опасения по поводу безопасности потоков становятся спорными.

7
ответ дан 1 December 2019 в 14:43
поделиться

Сохранение диспетчера сущностей открытым не позволяет ему вернуть соединение с пулом соединений.

Это может привести к ряду проблем, особенно в веб-приложениях, например когда пул работает на полную мощность и достигается максимальный размер соединения, ни один другой пользователь не может получить соединение с базой данных, препятствующее доступу к базе данных для этого пользователя.

В этом случае лучше иметь менеджеров с коротким сроком жизни, например открыть диспетчер сущностей в начале запроса и закрыть его в конце запроса (можно сделать с помощью слушателей / перехватчиков ..). Затем объекты отсоединяются, и вам необходимо повторно присоединить их, если вы хотите использовать их снова (с помощью операции слияния диспетчера сущностей).

5
ответ дан 1 December 2019 в 14:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: