Борьба за понимание правильного использования EntityManager
Я начинаю новый проект, и я совершенно не знаком с использованием JPA / Hibernate. Я пытаюсь понять, как правильно использовать EntityManager. Точнее, когда их создавать, сколько мне нужно, я должен закрыть их, должен ли я поместить все в транзакции?
В любом случае, в моем текущем коде, я получил org.hibernate.LazyInitializationException при попытке прочитать объект, который я ранее сохранил. Я бы понял обратное (чтение противовеса в транзакции, а затем попытка сохранить прочитанный объект в другой транзакции, но поскольку транзакция завершена, объект неуправляемый, поэтому сохранение не удается), но этого я не могу понять.
Я поместил свой код в GitHub ( https://github.com/GaetanLeu/intl ), это всего лишь пара classов. Моя основная часть находится в src / sandbox / MessageSandbox.java, и она не работает в строке 28 со следующей командой stacktrace:
- «Отключенный объект, переданный для сохранения ошибки» с кодом JPA / EJB
- JPA / Hibernate: отдельное лицо передано для сохранения
- Ошибка проверки: значение недействительно
- Правильное использование флеша () в JPA / Hibernate
- inverse = true в аннотациях JPA
Exception in thread "main" org.hibernate.LazyInitializationException: could not initialize proxy - no Session at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:164) at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:285) at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:185) at entity.MessageKey_$$_jvstfcc_0.toString(MessageKey_$$_jvstfcc_0.java) at java.lang.String.valueOf(String.java:2854) at java.lang.StringBuilder.append(StringBuilder.java:128) at com.google.common.base.Present.toString(Present.java:88) at java.lang.String.valueOf(String.java:2854) at java.io.PrintStream.println(PrintStream.java:821) at sandbox.MessageSandbox.main(MessageSandbox.java:28)
Также я получил предупреждение от Hibernate о том, что мой EntityManager уже существует, что происходит потом? Является ли метод EntityManagerFactory.createEntityManager возrotationм существующего?
WARN: HHH000436: Entity manager factory name (intl) is already registered. If entity manager will be clustered or passivated, specify a unique value for property 'hibernate.ejb.entitymanager_factory_name'
На самом деле я потерял, когда создавать EntityManagers ^^ Любая помощь была бы оценена, но, пожалуйста, простое объяснение. Я действительно новичок в этом.
О, BTW, я хочу точно сказать, что я не использую Spring, у меня нет EJB, я хочу манипулировать EntityManager вручную, пока не пойму. Благодаря 🙂
- Как настроить имя схемы по умолчанию в конфигурации JPA?
- Java - JPA - Генераторы - @SequenceGenerator
- Лучшая практика получения EntityManagerFactory
- IllegalStateException с Hibernate 4 и ManyToOne каскадом
- Hibernate: «Поле« id »не имеет значения по умолчанию»
- Пакетные вставки с JPA / EJB3
- Нужны ли мне элементы в файле persistence.xml?
- PersistenceContext EntityManager инъекции NullPointerException
СущностьManager управляет контекстом персистентности , другими словами, в снимке памяти состояния базы данных.
См. Что такое объект persistence?
Каждый объект, загруженный с помощью entityManager, будет находиться в управляемом состоянии (см. Жизненный цикл сущности), пока вы не закроете EM. Когда объект managed
, все изменения, внесенные в него, будут отслеживаться, а затем сохраняться при промывке ЭМ. Если вы получаете доступ к некоторому ленивому атрибуту, запрос будет автоматически инициирован для динамической загрузки данных, но если объект находится в состоянии отсоединения (если EM закрыт), доступ к ленивому атрибуту приведет к ошибке, которую вы получите.
Объем (/ жизненный цикл) вашего EM зависит от вашего контекста выполнения. Например, для веб-приложения для каждого HTTP-запроса обычно создается EM.
Для автономного приложения вам нужно учитывать, может ли firebase database обновляться другим приложением / нитью или нет. Если это возможно, ваш постоянный контекст может не соответствовать состоянию базы данных, и вы должны создать его для каждой единицы работы (транзакции), чтобы этого избежать. В противном случае вы можете создать один экземпляр один раз для всех приложений lifecyle и обновить его регулярно.
Для приложения CRUD жизненный цикл, как правило, следующий:
- создать EM
- выбор некоторых объектов (они управляются таким образом, любой доступ к ленивому атрибуту будет загружать данные из БД)
- закрыть EM (объект теперь отсоединен, любой доступ к ленивому атрибуту приведет к исключению LazyInitializationException)
- отображение данных пользователю
При проверке обновлений пользователей:
- создать их
- открыть транзакцию
- объедините (присоедините) свои обновленные сущности (это то, что вы вызываете save) (если вы настроили какую-то оптмическую блокировку, em проверит версию сущности на базе данных здесь)
- в конечном итоге выполнить некоторую проверку бизнеса или дополнительные обновления
- совершить транзакцию и закрыть em (изменения будут сброшены)
Имейте в виду, что EM – это легкий объект, дешевый для создания и уничтожения, а НЕ РЕЗЬБОЙ.
BTW, JPA – спецификация Java EE, которая является частью EJB (часть сохранения). Его цель заключается в использовании контекста контейнера Java EE (сервер приложений Java EE или CDI с JEE 6). Вы по-прежнему можете использовать hibernate в автономном режиме через контракт JPA, но даже в этом случае необходимо учитывать сцепление с пружиной, чтобы использовать возможности, управляемые контейнером.