Я полагаю, ответ таков: это зависит от обстоятельств .
Ваш менеджер сущностей - ключ к получению доступа к контексту, в котором находятся сущности. Если ваше приложение является приложением JSE, вы должны учитывать ожидаемую продолжительность жизни вашего контекста.
Предположим, вы создадите диспетчер сущностей по запросу пользователя. Итак, пока вы обслуживаете данный запрос, вы будете держать свой менеджер сущностей открытым, а когда вы закончите с ним, вы его закроете.
В приложении JSE вы, возможно, считали, что хотите, чтобы диспетчер сущностей оставался открытым на протяжении всей жизни приложения (предположим, что вы не имеете дело с большими объемами данных), а затем закрываете его, когда приложение завершает работу.
Итог: когда вы его открываете и когда закрываете, полностью зависит от вашей стратегии и вашего дизайна. Вы закрываете его, когда вам больше не нужны сущности в его контексте.
В вашем примере это не очевидно, но поскольку вы создаете EM в методе, вы должны закрыть его перед возвратом, иначе у вас больше не будет к нему доступа (если вы не сохраните его в каком-то реестре, что не видно в коде).
Если вы не закроете его, ваши сущности будут оставаться прикрепленными даже после того, как вы закончите их использовать. Ваш контекст будет сохранен, даже если вы больше не сможете получить доступ к своему EM.
Спецификация JPA содержит больше деталей. В разделе 7.7 Контексты сохраняемости, управляемые приложением, говорится:
Когда используется менеджер сущностей, управляемый приложением, приложение напрямую взаимодействует с фабрикой диспетчера сущностей поставщика сохраняемости для управления жизненным циклом диспетчера сущностей, а также для получения и уничтожения контекстов сохраняемости.
Все такие контексты персистентности, управляемые приложением, расширены по объему и могут охватывать несколько транзакций.
EntityManagerFactory.createEntityManager
Метод и
EntityManager
close
и isOpen
методы используются для управления жизненным циклом менеджера сущности приложения управляемого и связанный с ним контекст сохранения.
Расширенный контекст персистентности существует с момента создания диспетчера сущностей с использованием
EntityManagerFactory.createEntityManager
до закрытия диспетчера сущностей с помощьюEntityManager.close
.
Расширенный контекст персистентности, полученный от менеджера объектов, управляемого приложением, является автономным контекстом постоянства, он не распространяется с транзакцией.
[...] EntityManager.close
Метод закрывает диспетчер сущностей, чтобы освободить его постоянный контекст и другие ресурсы. После вызова close приложение не должно вызывать какие-либо другие методы EntityManager
экземпляра, кроме getTransaction
и isOpen
, в IllegalStateException
противном случае будет брошен вызов
. Если метод close вызывается, когда транзакция активна, контекст сохранения остается управляемым до завершения транзакции.
EntityManager.isOpen
Метод показывает, открыт ли управляющий объектом. isOpen
Метод возвращает истину , пока диспетчер объектов не был закрыт. Чтобы действительно понять, как это работает, важно понять отношения между менеджером сущностей и контекстом.
Итак, как вы можете видеть, диспетчер сущностей - это общедоступный интерфейс, через который вы получаете доступ к своим сущностям, однако ваши сущности находятся в контексте, прикрепленном к вашему диспетчеру сущностей. Понимание жизненного цикла различных типов контекстов ответит на ваш вопрос.
Контексты сохраняемости могут быть разных типов. В приложениях Java EE вы можете иметь либо контекст персистентности в области транзакции, либо контекст расширенного сохранения . В приложении JSE характер контекста контролируется разработчиком. .
Когда вы запрашиваете сущность у своего диспетчера сущностей, он ищет эту сущность в присоединенном контексте, если находит сущность там, то возвращает ее, в противном случае извлекает сущность из базы данных. Последующие вызовы этой сущности в контексте вернут ту же самую сущность.
В рамках транзакции
В приложении Java EE, использующем контекст персистентности в области транзакции, когда вы впервые обращаетесь к своему менеджеру сущностей, он проверяет, имеет ли текущая транзакция JTA присоединенный контекст, если контекст еще не присутствует, создается новый контекст и связывается менеджер сущностей. в этом контексте. Затем объект считывается из базы данных (o из кеша, если он есть), и помещается в контекст. Когда ваша транзакция завершается (фиксация или откат), контекст становится недействительным и все объекты в нем отсоединяются. Это классический сценарий для сессионных bean-компонентов без сохранения состояния.
@PersistenceContext(unitName="EmplService")
EntityManager em;
Это также означает, что в зависимости от того, как вы разрабатываете свои транзакции, вы можете получить более одного контекста.
Контекст с расширенным постоянством
В приложении Java EE с сессионными bean-компонентами с отслеживанием состояния вам может потребоваться, чтобы контекст выдерживал многократные вызовы bean-компонентов, поскольку вам не нравится фиксировать, пока bean-компонент не будет отмечен для удаления, верно? В этих случаях вам нужно использовать расширенный контекст сохранения. В этом случае контекст сохранения создается, когда он впервые нужен, но он не станет недействительным, пока вы не отметите компонент с сохранением состояния для удаления.
@PersistenceContext(unitName="EmplService", type=PersistenceContextType.EXTENDED)
Это означает, что независимо от экземпляра диспетчера сущностей, который вводится в этот компонент при последующих вызовах методов сеансовых компонентов с сохранением состояния, вы можете быть уверены, что всегда будете обращаться к одному и тому же контексту, и, следовательно, даже последующие вызовы будут возвращать тот же самый например, потому что это тот же контекст.
Кроме того, ваши изменения не будут сброшены до тех пор, пока компонент не будет помечен для удаления или вы не очистите его вручную.
Управляемый приложением
Вы всегда можете вручную создать экземпляр фабрики диспетчера сущностей и диспетчера сущностей. Это то, что вы обычно делаете в приложении JSE, верно?
Для такого рода приложений у вас обычно нет контейнера для обработки транзакций JTA, верно? Таким образом, вы используете локальные для ресурсов транзакции и несете ответственность за ручную фиксацию или откат изменений.
Для этого типа приложений, когда вы создаете экземпляр своего менеджера сущностей, к нему автоматически присоединяется контекст.
В зависимости от вашего приложения вы можете решить создать глобальный менеджер сущностей, жизненный цикл которого привязан к жизни самого приложения. Это единый менеджер сущностей на все время существования приложения. В этом случае ваш контекст будет создан и уничтожен вашим менеджером сущностей.
Или вы можете создать диспетчер сущностей для каждого разговора (т. Е. Транзакции) с пользователем вашего приложения. В этом случае объем определяется вами, но все же ваш контекст будет создан и уничтожен вашим менеджером сущностей.