Во время Hibernate Session
я загружаю некоторые объекты, и некоторые из них загружаются как прокси из-за отложенной загрузки. Все в порядке, и я не хочу отключать ленивую загрузку.
Но позже мне нужно отправить некоторые объекты (фактически один объект) клиенту GWT через RPC. И бывает, что этот конкретный объект является прокси. Поэтому мне нужно превратить его в настоящий объект. Я не могу найти метод, как "материализовать" в Hibernate.
Как я могу превратить некоторые объекты из прокси в действительные, зная их класс и ID?
На данный момент единственное решение, которое я вижу, - это извлечь этот объект из кэша Hibernate и перезагрузить его, но это действительно плохо по многим причинам.
HibernateProxy
определяетwriteReplace
метод, чтобы заставить разработчиков делать что-то особенное во время сериализации.(T)Hibernate.unproxy(entity)
Как я объяснил в этой статье , начиная с Hibernate ORM 5.2.10 , вы можете сделать это следующим образом:
До гибернации 5.2.10 . Самый простой способ сделать это - использовать метод unproxy, предлагаемый внутренней
PersistenceContext
реализацией Hibernate :источник
Department
со спискомStudent
, вам все еще нужноunproxy(department.getStudents())
- или достаточно простоunproxy(department)
?PersistentContext#unproxy(proxy)
выдает исключение, если прокси не инициализирован во времяHibernate.unproxy(proxy)
иLazyInitializer#getImplementation(proxy)
инициализирует прокси при необходимости. Просто поймали исключение из-за этой разницы. ;-)Попробуй использовать
Hibernate.getClass(obj)
источник
Я написал следующий код, который очищает объект от прокси (если они еще не инициализированы)
Я использую эту функцию поверх результатов моих служб RPC (через аспекты), и она рекурсивно очищает все объекты результатов от прокси (если они не инициализированы).
источник
Способ, который я рекомендую с JPA 2:
источник
В Spring Data JPA и Hibernate я использовал подынтерфейсы
JpaRepository
для поиска объектов, принадлежащих иерархии типов, которая была отображена с использованием стратегии «соединения». К сожалению, запросы возвращали прокси базового типа, а не экземпляры ожидаемых конкретных типов. Это помешало мне привести результаты к правильным типам. Как и вы, я приехал сюда в поисках эффективного способа избавить мои энтузиасты.У Влада есть правильная идея снять эти результаты; Яннис дает немного больше деталей. В дополнение к их ответам, вот что вы можете искать:
Следующий код обеспечивает простой способ отсоединения прокси-объектов.
Вы можете передавать в метод незаксируемые объекты или объекты с прокси
unproxy
. Если они уже без прокси, они просто будут возвращены. В противном случае, они будут освобождены от прокси и возвращены.Надеюсь это поможет!
источник
Другой обходной путь должен позвонить
Прямо перед закрытием сессии.
источник
Я нашел решение отменить класс, используя стандартные API Java и JPA. Протестировано с hibernate, но не требует hibernate в качестве зависимости и должно работать со всеми поставщиками JPA.
Единственное требование - необходимо изменить родительский класс (Address) и добавить простой вспомогательный метод.
Общая идея: добавить вспомогательный метод в родительский класс, который возвращает сам себя. когда метод вызывается через прокси, он переадресует вызов реальному экземпляру и возвращает этот реальный экземпляр.
Реализация немного сложнее, поскольку hibernate распознает, что прокси-класс возвращает себя и все еще возвращает прокси вместо реального экземпляра. Обходной путь - обернуть возвращаемый экземпляр в простой класс-оболочку, тип класса которого отличается от реального экземпляра.
В коде:
Чтобы привести Address proxy к реальному подклассу, используйте следующее:
источник
Начиная с Hiebrnate 5.2.10 вы можете использовать метод Hibernate.proxy для преобразования прокси в вашу реальную сущность:
источник
Спасибо за предложенные решения! К сожалению, ни один из них не сработал для моего случая: получение списка объектов CLOB из базы данных Oracle через JPA - Hibernate с использованием собственного запроса.
Все предложенные подходы дали мне либо ClassCastException, либо просто вернули java Proxy-объект (который глубоко внутри содержал желаемый Clob).
Таким образом, мое решение заключается в следующем (на основе нескольких вышеуказанных подходов):
Надеюсь, это кому-нибудь поможет!
источник