Hibernate - pobieranie calego obiekty vs pobieranie fragmentu (master-detail)

0

Mamy pewna zmapowana klase, ktora sama w sobie nie jest dosc spora, ale posiada pare zmapowanych kolekcji. Mamy 2 use casy:

  1. pobieranie calego obiektu wraz z kolekcjami zeby pokazac detale, wylistowac wszystkie kolekcje itp
  2. wyszukiwanie - pokazujemy tylko obiekty ktore spelniaja kryteria, i tylke podstawowe dane; po kliknieciu na element z wyszukanej listy idziemy do detali, czyli pkt. 1

W tej chwili jest to zrobione tak, ze na ta sama tabele sa 2 mapowania, jedno ktore ma w sobie wszystkie kolekcje itp. (do detali) i jedno (read only) ktore pobiera tylko czesc danych (do widoku master w liscie wyszukiwania). Niby dziala, ale nie podoba mi sie pare rzeczy, przede wszystkim to ze uzywany jest 2nd level cache, i wszysko sie spierdolilo. Taki use case:

  1. wyszukujemy liste i dostajemy klikamy w jakis obiekt, ktory ma status A
  2. w widoku detali zmieniamy status na B, zapisujemy
  3. znowu szukamy na podstawie tych samych kryteriow, i dostajemy ten sam obiekt, ale ze starym statusem.
    Problemu szukalem dzisiaj caly dzien (nie ja pisalem ten system i go nie znam, koles ktory pisze nie ma wiekszego pojecia i nie umie opdowiadac na pytania) i znalazlem: otoz, uzywamy ehcache i pierwsze zapytanie jest do encji dajmy na to SearchDTO (a wiec taki ma klucz), gdy zapisujemy zmieniamy jednak obiekt klasy FullWypas, i on jest updatowany w cache, a gdy nastepnie szukamy, zwracane sa zcachowane wyniki z poprzedniego zapytania, i nie sa sprawdzane z baza poniewaz zapis dokonal inwalidacji innego regionu! Myslalem ze mnie krew zaleje, ale ok. Naprawilem to tak ze po akcjach ktore mutuja obiekty FullWypas dokonywana jest operacja evict(SearchDTO, <id instancji FullWypas>) i wszyskto teraz dziala. Nie podoba mi sie to rozwiazanie.

Ja bym wolal zrobic tak, zeby byla tylko 1 zmapowana encja, ktora wszyskie relacje ma lazy, i wyszukiwanie zwraca tylko te podstawowe dane (kolekcje nie beda inicjalizowane, wiec nie beda pobierane dane*). Gdy idziemy do widoku detali, pobieramy wszystkie dane razem z kolekcjami za pomoca hql z fetch join, wzglednie po pobraniu wywolujemy size() lub iterator() na kazdej kolekcji zeby ja zainicjalizowac i doladowac (wzglednie, Hibernate.initialize()). Co o tym myslicie? Jak sie takie cos poprawnie implementuje? Macie jakies inne pomysly?

  • Do renderowania detali potrzebujemy wszystkich kolekcji itp., poniewaz w momencie renderingu strony sesja hibernate juz jest zamknieta i nie mozna sobie doladowac na zawolanie. Uzywamy wicket, i podobno tam sie tak robi, ale moze mi ktos powie jak to zrobic inaczej? OpenSessionInView nie zadziala tutaj.
0

JAko ciekawostkę, w jednym z projektów mieliśmy podobną sytuację (w sensie szukajka i detale), z tym że do szukajki było szukanie pełnotekstowe (HSearch) i aktualizacją pól/indexów opiekował się Hibernate, dane które były wyświetlane w szukajce były dołączone do indexów, więc zapytanie nawet nie dotykało bazy, za pomocą result transformerów Hibernate zmienialiśmy wynik z szukania pełnotekstowego na encję która w sumie miała tylko zainicjowane pola potrzbne do szukajki, reszta nule. Strona szczegułów była genereowana podobnie do tego co zaproponowałeś, z tą róźnicą żę fetcha używaliśmy tylko do asocjacji 1 - 1, reszta w osobnych zapytaniach (hibernate potrafił porobić takie joiny że serwer bazy klękał, bardzo dużo acocjacji), oczywiście wszystko na lazy.Akurat liczba asocjacji była duża ale nie zmieniała się często, więc keszowaliśmy całość jako wynik metody z serivce'u.
Różne mapowania na tą samą encję byłyby wygodne tylko w przypadku kiedy nie trzeba myśleć co chwilę co miałbym w keszu odświeżać.
Inna sprawa, że nawet jak masz encja jako "keszowalną" to second lvl keszuje obiekty po kluczu, więc i tak nie sprawdzi się do wyszukiwarki (chyba że query cache, ale wtedy to już w ogóle zawrót głowy :D)

0

Tutaj jest tak:
a. encje powinny byc wczytywane na raz, bo rendering wymaga pokazania na raz wszystkich kolekcji - poki co fetch join / eager kolekcje nie sa wolne (moze sie to zmieni)
b. wlasnie chodzi o query cache - klucze sa tworzone z zapytania oraz parametrow, szukanie uzywa SearchDTO i tak zapisuje; podczas updatu encji ona ma tym FullWypas i update 2nd level cache jest robiony, ale dla tego typu, a nie dla SearchDTO, stad problem (ale rozwiazany)
c. o apache lucene ludzie w firmie nie slyszeli, a o HibernateSearch tym bardziej, mimo ze od 10 lat pizgaja wszystko w spring-hibernate; co wiecej, napisali wlasny generatow sql ktory robi pelno warunkow like itp. i sklejaja zapytania, dzieki czemu wspieramy tylko oracle ;d; jak szybkie to jest nie musze wspominac; no coz, ja tu tylko sprzatam ;d

1 użytkowników online, w tym zalogowanych: 0, gości: 1