Efektywny dostęp do dużych danych tworzących listę, poprzez podzielenie ich na fragmenty.
Aplikacje bazodanowe często wymagają przesyłania do użytkownika długich list danych, takich jak katalogi lub wyniki wyszukiwania. W takich przypadkach prezentacja całej listy na raz jest zazwyczaj niepotrzebna (ponieważ użytkownik nie jest zainteresowany całością) lub niemożliwa (nie ma wystarczającej ilości miejsca na elementy).
Pobierając listę elementów, bardzo kosztowne byłoby użycie ziaren entity beans. Duży koszt wynika, po pierwsze, z użycia zdalnych metod do wyszukiwania ziaren, po drugie z użycia zdalnych metod dostępu do danych przechowywanych w ziarnach.
Powyższe problemy mogą zostać uniknięte dzięki zastosowaniu iteratora (page-by-page iterator) . Poprzez iterator użytkownik może przeglądać listę elementów podzieloną na okna (page). Wielkość okna może być duża lub mała, w zależności od wymagań klienta.
Iterator powinien być używany do dostępu do dużych list danych znajdujących się po stronie serwera gdy:
użytkownik jest zainteresowany tylko częścią danych za jednym razem.
Cała lista nie może zostać pokazana na raz, ponieważ się nie mieści.
nie ma wystarczającej ilości pamięci do wczytania całej listy.
przesłanie całej listy na raz zajęłoby za dużo czasu.
Zastosowanie iteratora ma następujące konsekwencje:
Mniej danych jest przesyłanych z serwera. Klienci otrzymują tak dużo, lub tak mało danych, jak potrzebują. Lista nie musi być przesyłana w całości.
Więcej żądań jest wysyłanych do serwera. Ponieważ lista nie jest przesłana za jednym razem, niezbędne są żądania pobrania kolejnych stron listy.
Iterator może błędnie prezentować dane. Zgodnie ze wzorcem, iterator nie posiada własnej kopii przeglądanej listy. W związku z tym, wstawianie i usuwanie elementów listy będzie kolidowało z przeglądaniem za pomocą iteratora. Iterator może zwrócić ten sam element dwa razy, lub nie pokazać określonego elementu ani razu.
Na szczęście bezwzględna poprawność danych nie jest zazwyczaj wymagana, ponieważ iterator stosuje się do przeglądania i nie ma niebezpieczeństwa zapisu niespójnych danych. Ponadto duże kolekcje danych są zazwyczaj statyczne i zmieniają się stosunkowo rzadko.
Iterator przechowuje pozycję użytkownika w przeglądanej liście danych. Zawiera metody zwracające następną oraz poprzednią stronę, oraz ustawiające wielkość strony.
Jest kilka sposobów implementacji iteratora:
Za pomocą fast-lane readera. Przy tej metodzie, iterator używa fast-lane readera do pobierania elementów listy bezpośrednio ze źródła zasobu. Jest to wskazana matoda, jeśli dane nie muszą być pobierane w obrębie transakcji.
Jako stanowy session bean. Wedlug tej strategii, ziarno przechowuje stan iteracji. Ponadto przechowuje cache elementów pobranych z serwera, dzięki czemu przyspiesza ponowny dostęp do tych samych danych.
Ta metoda może być kosztowna ze względu na zużycie zasobów, zwłaszcza pamięci, ponieważ cache jest tworzony dla każdego klienta osobno.
Jako bezstanowy session bean. W tej metodzie, ziarno przechowuje wspólny cache elementów dla wszystkich klientów. Dzięki temu zmniejsza się zużycie zasobów, oraz przyspiesza działanie, ponieważ zwiększa prawdopodobieństwo skorzystania z cache'u przy pobieraniu elementów.
Jednakże ze względu na to, że ziarno jest bezstanowe, nie może przechowywać stanu iteracji (pozycji przeglądanych danych), w związku z czym klient musi za każdym razem sam podawać, który fragment listy chce pobrać.
Poniższe wskazówki stosują się niezależnie od wybranej metody implementacji:
Iterator powinien zwracać kolekcję elementów Value Object. Jest to znacznie wydajniejsza metoda, niż znajdywanie, przekazywanie i używanie kolekcji ziaren EJB.
Jeśli iterator jest implementowany jako session bean, elementy listy muszą być obiektami serializowalnymi.
Połączenie ze źródłem zasobu powinno być zamykane po każdym wywołaniu iteratora, w przeciwnym wypadku klienci nie będą mogli przeglądać tych samych danych współbieżnie.
Obciążenie sieci oraz serwera. Wielkość stron iteratora ma wpływ na dwa czynniki. Im mniejsza strona, tym więcej żądań klientów jest kierowanych do serwera, lecz potencjalnie mniej danych jest przesyłanych przez sieć. Analogicznie im większa strona, tym mniejsze obciążenie serwera, natomiast większe przeciążenie sieci i większy czas oczekiwania na dane.
Przy szybkich sieciach, zazwyczaj jest lepiej używać dużych stron iteratora, żeby zwiększyć szansę, że użytkownik nie będzie musiał pobierać dalszych stron. Przy wolnych połączeniach sieciowych, warto zmniejszyć wielkości strony, żeby zmniejszyć obciążenie sieci oraz frustrację użytkownika, oczekującego na stronę.
Warto stosować cache. Przechowywanie pobranych już raz zasobów potencjalnie zmniejsza obciążenie serwera i łącza z nim, oraz przyspiesza dostęp do danych. Należy pamiętać jednak, że cache może być przyczyną otrzymania przez klienta nieaktualnych danych.
Cache może wymagać ustawienia limitu wielkości. Warto zastosować schemat high-watermark, polegający na usuwaniu tych danych przekraczających limit, które są najstarsze.