Вопрос по java – Должен ли JPA Entity Manager быть закрыт?

68

У меня есть метод ниже.

public Profile readUser(String email){
    EntityManager em = EMF.get().createEntityManager();
    return em.find(Profile.class, email);
}

Можно ли использовать вышеприведенное использование менеджера сущностей? Или нужно закрыть их? Есть предложения, пожалуйста.

Нет, просто нет. Если вы не хотите утечки ... user8558216
Возможный дубликат Должен ли я закрыть () каждый EntityManager? rds

Ваш Ответ

1   ответ
113

это зависи.

Ваш менеджер сущностей является ключом для получения доступа к контексту, в котором находятся сущности. Если ваше приложение является приложением JSE, вы должны учитывать, какова продолжительность жизни вашего контекста.

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

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

Итог, когда вы его открываете и когда закрываете, полностью зависит от вашей стратегии и вашего дизайна. Вы закрываете его, когда вам больше не нужны сущности в его контексте.

В вашем примере это не очевидно, но поскольку вы создаете EM в методе, вы должны закрыть его перед возвратом, иначе у вас больше не будет доступа к нему снова (если вы не храните его в каком-то реестре , что не видно в коде).

Если вы не закроете его, ваши сущности будут сохранены как прикрепленные, даже после того, как вы их закончили. Ваш контекст будет поддерживаться, даже если вы больше не сможете получить доступ к своему EM.

TheJPA Спецификация содержит больше деталей. В разделе 7.7 Контексты управляемости приложениями это говорит:

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

Все такие контексты персистентности, управляемые приложением, расширены по объему и могут охватывать несколько транзакций.

TheEntityManagerFactory.createEntityManager метод иEntityManager close а такжеisOpen методы используются для управления жизненным циклом менеджера сущностей, управляемого приложением, и связанного с ним контекста персистентности.

Расширенный контекст постоянства существует с того момента, когда менеджер сущностей был создан с помощьюEntityManagerFactory.createEntityManager пока менеджер сущностей не будет закрыт с помощьюEntityManager.close.

Расширенный контекст персистентности, полученный от менеджера сущностей, управляемого приложением, является автономным контекстом персистентности, который не распространяется с транзакцией.

[...] TheEntityManager.closeетод @ закрывает менеджер сущностей, чтобы освободить его постоянный контекст и другие ресурсы. После вызова close приложение не должно вызывать какие-либо дополнительные методы дляEntityManager экземпляр за исключениемgetTransaction а такжеisOpen, илиIllegalStateException будет брошено. Если метод close вызывается при активной транзакции, контекст постоянства остается управляемым до завершения транзакции.

TheEntityManager.isOpen метод указывает, открыт ли менеджер сущностей.isOpenетод @ возвращает true, пока менеджер сущностей не будет закрыт. Чтобы действительно понять, как это работает, важно понять отношения между менеджером сущностей и контекстом.

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

онтексты персистентности могут быть разных типов. В приложениях Java EE вы можете иметь либо контекст сохраняемости транзакции или расширенный персистентный контекст. В приложении JSE характер контекста равен контролируется разработчиком.

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

Сделка в области видимости

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

@PersistenceContext(unitName="EmplService")
EntityManager em;

Это также означает, что в зависимости от того, как вы разрабатываете свои транзакции, у вас может быть более одного контекста.

Расширенный постоянный контекст

В приложении Java EE с сессионными компонентами с сохранением состояния вам может понадобиться, чтобы контекст выдержал множественные вызовы bean-компонентов, поскольку вы не любите коммитить, пока компонент не будет помечен для удаления, верно? В этих случаях вам нужно использовать расширенный контекст постоянства. В этом случае контекст персистентности создается при первой необходимости, но он не станет недействительным до тех пор, пока вы не отметите bean-компонент с состоянием для удаления.

@PersistenceContext(unitName="EmplService", type=PersistenceContextType.EXTENDED)

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

Кроме того, ваши изменения не будут сброшены до тех пор, пока компонент не будет помечен для удаления или вы не сбросите их вручную.

Применение управляемого

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

Для таких приложений у вас обычно нет контейнера для транзакций JTA, верно? Таким образом, вы используете локальные ресурсные транзакции и несете ответственность за ручное принятие или откат изменений.

Для такого типа приложений, когда вы создаете экземпляр вашего менеджера сущностей, к нему автоматически присоединяется контекст.

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

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

Отличный ответ, но мне нужно знать: открывать и закрывать EntityManager несколько раз во время сеанса имеют высокую производительность? Создавать и закрывать только один раз, или создавать / использовать / закрывать его в каждой операции с базой данных, каков наилучший подход? «это зависит», хорошо, но должно иметь более подходящее использование в большинстве случаев .. tomrlh
@ tomurlh Насколько я понимаю, стоимость созданияEntityManager должно быть незначительным. С моей точки зрения EntityManager - это просто абстракция для работы с блок работы текущей транзакции. Я считаю, что это прекрасно для создания и уничтожения одного за транзакцию. Теперь у него есть другие последствия, потому чтоEntityManager серверы в качестве кеша транзакций для ваших сущностей и, следовательно, имеющие четко определенную область транзакций и правильное обращение с сущностями, могут использовать этот кеш. Edwin Dalorzo

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