Podczas hibernacji Session
ładuję niektóre obiekty, a niektóre z nich są ładowane jako proxy z powodu leniwego ładowania. Wszystko jest w porządku i nie chcę wyłączać leniwego ładowania.
Ale później muszę wysłać niektóre obiekty (właściwie jeden obiekt) do klienta GWT za pośrednictwem RPC. I zdarza się, że ten konkretny obiekt jest proxy. Muszę więc przekształcić go w prawdziwy obiekt. Nie mogę znaleźć metody takiej jak „materializacja” w Hibernate.
Jak zmienić niektóre obiekty z serwerów proxy w rzeczywiste, znając ich klasę i identyfikator?
W tej chwili jedynym rozwiązaniem, które widzę, jest wyrzucenie tego obiektu z pamięci podręcznej Hibernate i ponowne załadowanie go, ale jest to naprawdę złe z wielu powodów.
HibernateProxy
określawriteReplace
sposób, aby wymusić implementors zrobić coś wyjątkowego podczas serializacji.(T)Hibernate.unproxy(entity)
Jak wyjaśniłem w tym artykule , od Hibernate ORM 5.2.10 możesz to zrobić tak:
Przed hibernacją 5.2.10 . najprostszym sposobem na to było użycie metody nieproxy oferowanej przez wewnętrzną
PersistenceContext
implementację Hibernate :źródło
Department
z ListąStudent
, czy nadal musiszunproxy(department.getStudents())
- czy wystarczyunproxy(department)
?PersistentContext#unproxy(proxy)
zgłasza wyjątek, jeśli proxy nie jest zainicjowane podczasHibernate.unproxy(proxy)
iLazyInitializer#getImplementation(proxy)
inicjuje proxy, jeśli to konieczne. Właśnie złapałem wyjątek z powodu tej różnicy. ;-)Spróbuj użyć
Hibernate.getClass(obj)
źródło
Napisałem następujący kod, który czyści obiekt z serwerów proxy (jeśli nie są jeszcze zainicjowane)
Używam tej funkcji na wynikach moich usług RPC (poprzez aspekty) i czyści ona rekurencyjnie wszystkie obiekty wynikowe z serwerów proxy (jeśli nie są zainicjowane).
źródło
Sposób, w jaki polecam z JPA 2:
źródło
W Spring Data JPA i Hibernate używałem podinterfejsów programu
JpaRepository
do wyszukiwania obiektów należących do hierarchii typów, która została zmapowana przy użyciu strategii „łączenia”. Niestety, zapytania zwracały serwery proxy typu podstawowego zamiast wystąpień oczekiwanych typów konkretnych. To uniemożliwiło mi rzutowanie wyników na prawidłowe typy. Tak jak ty, przyjechałem tutaj, szukając skutecznego sposobu na uwolnienie moich podmiotów.Vlad ma dobry pomysł na odblokowanie tych wyników; Yannis podaje trochę więcej szczegółów. Dodając do ich odpowiedzi, oto reszta tego, czego możesz szukać:
Poniższy kod zapewnia łatwy sposób na usunięcie proxy jednostek proxy:
Do
unproxy
metody można przekazać niezarejestrowane jednostki lub jednostki proxy . Jeśli nie są już zabezpieczone, zostaną po prostu zwrócone. W przeciwnym razie zostaną pozbawione proxy i zwrócone.Mam nadzieję że to pomoże!
źródło
Innym sposobem obejścia problemu jest zadzwonić
Tuż przed zamknięciem sesji.
źródło
Znalazłem rozwiązanie do deproxyingu klasy przy użyciu standardowego API Java i JPA. Testowane z hibernacją, ale nie wymaga hibernacji jako zależności i powinno działać ze wszystkimi dostawcami JPA.
Jedno wymaganie - konieczne jest zmodyfikowanie klasy nadrzędnej (Adres) i dodanie prostej metody pomocniczej.
Ogólna idea: dodaj metodę pomocniczą do klasy nadrzędnej, która zwraca się sama. gdy metoda zostanie wywołana na serwerze proxy, przekieruje wywołanie do rzeczywistej instancji i zwróci tę rzeczywistą instancję.
Implementacja jest nieco bardziej złożona, ponieważ hibernacja rozpoznaje, że klasa proxy zwraca samą siebie i nadal zwraca serwer proxy zamiast rzeczywistej instancji. Obejście polega na umieszczeniu zwracanej instancji w prostej klasie opakowania, która ma inny typ klasy niż rzeczywista instancja.
W kodzie:
Aby przesłać adres proxy na rzeczywistą podklasę, użyj następujących poleceń:
źródło
Począwszy od Hiebrnate 5.2.10 możesz użyć metody Hibernate.proxy , aby przekonwertować serwer proxy na swoją rzeczywistą jednostkę:
źródło
Dziękuję za zaproponowane rozwiązania! Niestety żaden z nich nie zadziałał w moim przypadku: odebranie listy obiektów CLOB z bazy danych Oracle przez JPA - Hibernate, przy użyciu natywnego zapytania.
Wszystkie proponowane podejścia dały mi albo ClassCastException, albo po prostu zwróciły obiekt Java Proxy (który głęboko w środku zawierał pożądany Clob).
Więc moje rozwiązanie jest następujące (oparte na kilku powyższych podejściach):
Mam nadzieję, że to komuś pomoże!
źródło