JPA: какие реализации поддерживают ленивую загрузку внешних транзакций?

EclipseLink может загружать ленивые отношения в сущности даже после того, как созданный ими менеджер объектов больше не доступен. С Hibernate это не работает или, по крайней мере, не было во время этой публикации.

Как насчет других провайдеров? OpenJPA и DataNucleus в частности?

Каковы недостатки этого (кроме более сложной реализации)?

Ответы

Ответ 1

Хотя для Hibernate требуется, чтобы тот же EntityManager был доступен для ленивой загрузки объектов, легко достичь гибкой ленивой загрузки с помощью Открыть сеанс в представлении шаблон. По сути, вы держите EntityManager открытым до тех пор, пока вам это нужно. Я разработал клиентские приложения, которые сохраняют один и тот же EntityManager открытым до тех пор, пока приложение открыто. Это дало бы вам по существу то же самое поведение, описанное в статье. Тем не менее, это, конечно, сложнее реализовать, чем "из коробки", которую описывает ленивая загрузка Roman.

Все, что сказано, есть недостатки для ленивой загрузки. Разработчик должен знать свою стратегию выбора и должен быть способен дифференцировать, когда и где каждая стратегия наиболее применима. В противном случае вы можете столкнуться с серьезными проблемами производительности, такими как N + 1 Select Problem. Плюс всегда есть вероятность, что вы получите исключение базы данных во время рендеринга представления.

О OpenJPA и DataNucleus: хотя я никогда не использовал их, этот пост указывает, что OpenJPA также требует OpenSessionInViewFilter для ленивой загрузки, Этот ответ SO и этот пост форума указывают, что DataNucleus требует OpenPersistenceManagerInViewFilter для ленивая загрузка.

Ответ 2

Обратите внимание, что Hibernate 4.1.6 добавила поддержку для загрузки ленивых данных вне транзакций через свойство hibernate.enable_lazy_load_no_trans JPA.

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

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

Ответ 3

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

DataNucleus JPA будет отлично выполнять ленивую загрузку полей за пределами транзакций. Очевидно, вам нужно указать, используете ли вы контекст постоянства TRANSACTION или EXTENDED, потому что в первом случае объекты получают DETACHED при совершении транзакции (и вы не можете ленить нагрузку после снятия), а в последнем объекты остаются MANAGED (и вы можете лениво загрузить в этой ситуации).