Создает ли метод find () EntityManager новый экземпляр класса JPA? - PullRequest
7 голосов
/ 12 мая 2011

Я немного растерялся.Вопрос в заголовке, и вот почему я спрашиваю.У меня есть веб-приложение JSF + JPA, работающее на одной виртуальной машине.И класс JPA имеет поле @Transient.Теперь представьте, что какой-то веб-пользователь открывает какую-то страницу и выполняет код ниже

import javax.persistence.EntityManager;
// method 1 in backing bean
Agent a = entityManager.find(Agent.class, "007");
a.setTransientValue("Aston Martin");

Какой вывод я должен ожидать, когда другой веб-пользователь / поток пытается прочитать это временное значение:

// method 2 in backing bean
Agent a = entityManager.find(Agent.class, "007");
String val = a.getTransientValue();

В другомсловами, а в терминах JVM метод find() всегда возвращает новый экземпляр класса или один и тот же или «это зависит»?Я просмотрел JSR-220 для ответа, но безуспешно, любая помощь или ссылка на документ были бы признательны.

Ответы [ 2 ]

7 голосов
/ 12 мая 2011

Если вы вызываете find(..) в одном и том же сеансе (то есть в течение одного и того же времени существования entitymanager), будет возвращена та же ссылка на объект.Документация find() определяет это:

Если экземпляр сущности содержится в контексте постоянства, он возвращается оттуда.

Другими словами, EntityManager содержит коллекцию (наиболее вероятную карту) сущностей.Когда вы звоните find, он проверяет эту коллекцию.Если сущность там не найдена, делается запрос к базе данных.Возвращенный объект помещается в карту, поэтому последующие вызовы найдут его там.

Но еще раз отметим, что это только на протяжении одного сеанса.Обычно это то же самое, что один HTTP-запрос (в контексте веб-приложения)

5 голосов
/ 16 мая 2011

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

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

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

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

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

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

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

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

Контекст расширенного постоянства

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

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

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

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

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

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

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

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

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

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

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