2012-05-26 3 views
65

У меня есть метод ниже.Должен ли быть закрыт администратор JPA?

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

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

+0

Возможный дубликат [Мне нужно закрыть() каждый EntityManager?] (Http://stackoverflow.com/questions/220374/do-i-have-to-close-every-entitymanager) – rds

+0

Нет, просто нет , Если вы не хотите утечки ... – DN1

ответ

105

Я полагаю, что ответ: это зависит от.

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

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

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

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

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

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

JPA Specification содержит более подробную информацию. В разделе 7.7 Применение управляемого Стойкости контексты он говорит:

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

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

EntityManagerFactory.createEntityManager метод и EntityManagerclose и isOpen методы используются для управления жизненным циклом менеджера объекта приложения управляемого и связанный с ним контекст настойчивость.

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

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

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

Метод EntityManager.isOpen указывает, открыт ли администратор объекта . Метод isOpen возвращает значение true до тех пор, пока администратор объекта не будет закрыт . Чтобы понять, как это работает, очень важно понять взаимосвязь между менеджером сущности и контекстом.

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

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

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

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

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

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

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

Продлены Постоянство Контекст

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

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

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

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

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

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

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

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

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

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

+0

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

+1

@tomurlh. Насколько мне известно, стоимость создания «EntityManager» должна быть незначительной. С моей точки зрения, EntityManager - это просто абстракция для работы с [единицей работы] (https://martinfowler.com/eaaCatalog/unitOfWork.html) текущей транзакции. Я считаю, что совершенно нормально создавать и уничтожать одну транзакцию. Теперь это имеет другие последствия, потому что серверы EntityManager в качестве транзакционного кэша для ваших объектов и, следовательно, имеющие четко определенную область транзакций и надлежащее обращение с сущностями, могут воспользоваться этим кешем. –

Смежные вопросы