2014-11-03 9 views
5

Próbuję utworzyć nowy Page przy użyciu listy obiektów pobranych z bazy danych. Najpierw otrzymuję wszystkie elementy z DB, konwertuję je do strumienia, a następnie używam lambda do filtrowania wyników. Następnie potrzebuję strony z określoną liczbą elementów, jednak utworzenie nowej wartości PageImpl nie zwróci strony o prawidłowym rozmiarze.Strona danych sprężyn Nie powracasz na stronę o poprawnym rozmiarze?

Oto mój kod:

List<Produtos> listaFinal; 
Stream<Produtos> stream = produtosRepository.findAll().stream(); 
listaFinal = stream.filter(p -> p.getProdNome().contains("uio")).collect(Collectors.toList()); 

long total = listaFinal.size(); 
Page<Produtos> imp = new PageImpl<>(listaFinal,pageable,total); 

Oto zrzut ekranu z debugowania:

Uwaga wielkość w stronicowalnej obiektu jest ustawiona na 20, a ona rozumie, że potrzebuje 4 strony aby wyświetlić 70 elementów, ale zwraca całą listę.

Czego mi brakuje?

Edycja odpowiedzi na komentarz wykonany przez Tomasza:

rozumiem jak używać stronę, aby powrócić tylko kawałek danych. Kod, który pokazałem, był moją próbą użycia wyrażenia lambda do filtrowania mojej kolekcji. Problemem dla mnie jest to, że chcę użyć lambda Java 8, aby wysłać zapytanie do bazy danych poprzez Spring Data JPA. Jestem przyzwyczajony do wyrażeń zapytań VB.NET i Entity function(x) i zastanawiałem się, jak to samo zrobić z Spring JPA.

W moim repozytorium używam extends JpaRepository<Produtos, Integer>, QueryDslPredicateExecutor<Produtos>, co daje mi dostęp do findAll(Predicate,Pageable). Jednak predykatu nie wpisano, więc nie mogę po prostu użyć w zapytaniu p -> p.getProdNome().contains("uio"). Używam SQL Server i Hibernate.

Odpowiedz

4

Po dowiedzeniu się więcej o działaniu danych sprężynowych, skorzystałem z adnotacji @Query dotyczących moich metod w implementacjach JpaRepository, aby poprawnie wysłać zapytanie do bazy danych i przefiltrować wyniki, eliminując konieczność korzystania ze strumienia, a następnie konwersji z powrotem na stronę.

Oto jak powyższy kod będzie wyglądać w przypadku gdy ktoś potrzebuje przykład:

@Query("select p from Produtos p where p.prodNome = ?1") 
public Page<Produtos> productsListByName(String prodNome, Pageable pageable) 

Im świadomy findBy metod wiosnę, ale czasami nazwy metod stają się naprawdę trudne do odczytania w zależności od ilości parametrów, więc po prostu przykleiłem się do JPQL.

W ten sposób zawartość strony będzie zawsze zawierała maksymalną liczbę elementów zdefiniowanych w konfiguracji wiosennej.

Używam również niestandardowej implementacji PageImpl, Nie jestem teraz w pracy i nie mam dostępu do kodu, ale opublikuję go, kiedy tylko będę mógł.

Edit: wdrożenie niestandardowych można znaleźć here

+0

Nice! Zrobię to z tym, nad czym pracuję. – stites

+0

Czy możesz podać mi kod, którego używasz do PageImpl? Mam teraz ten sam problem! – user3127109

+0

Kod został dodany. Zauważ, że ta implementacja była potrzebna w moim przypadku, ponieważ miałem do czynienia z usługą REST, a domyślna implementacja nie działała dla mnie, może być inna w twoim przypadku. – dubonzi

2

Jeśli dobrze zrozumiałem twój kod, to twoim zamiarem jest załadowanie wszystkich rekordów z bazy danych i podzielenie ich na x segmentów zebranych w PageImpl, prawda?

To nie jest sposób w jaki działał. Obecna intencja abstrakcji Pageable i Page NIE jest wymagana, aby przesyłać zapytania do wszystkich danych, ale tylko "wycinek" danych, które są potrzebne.

W twoim przypadku możesz wysłać zapytanie do danych przez Page<X> page = repository.findAll(pageable); i po prostu je zwrócić. Strona zawiera zapisy dla bieżącej strony wraz z dodatkowymi informacjami, takimi jak np. Całkowita liczba rekordów i czy jest następna strona.

W kodzie klienta można użyć tych informacji do renderowania listy rekordów i generowania odpowiednio linków next/prev. Należy zauważyć, że zapytanie z Page<X> jako typem wyniku powoduje 2 zapytania (1, aby określić całkowitą liczbę wszystkich zapytań i 1 dla rzeczywistych danych strony).

Jeśli nie potrzebujesz informacji o łącznej liczbie wyników, ale nadal chcesz mieć możliwość wygenerowania następnego linku, powinieneś użyć jako Slice<X> jako typu zwrotu - ponieważ powoduje to tylko jedno zapytanie.

+0

Edytowałem moje oryginalne pytanie z moim komentarzem, ponieważ było zbyt długo, aby pisać tutaj, proszę spojrzeć! Dzięki. – dubonzi

+0

Mam do czynienia z tym samym problemem. Muszę użyć DTO, aby odwzorować dane wyjściowe zapytania, aby usunąć niektóre ukryte kolumny. Najpierw otrzymuję wszystkie wyniki, a następnie odwzorowuję wynik na nowe wyniki zgodnie z DTO. następnie używam PageImpl na nowym wyniku. Ale pokazuje wszystkie rekordy zamiast informacji stronicowanych. –

2

PageImpl nie jest przeznaczony do wykonywania jakiejkolwiek paginacji listy. From the docs widać, że jest to tylko "podstawowa implementacja Page", która brzmi prawie tak, jak tego chcesz, ale jest to naprawdę mylące.

Użyj PagedListHolder, który jest prostym uchwytem stanu do obsługi list obiektów, dzieląc je na strony.

0

Aby przedłużyć stite's answer, A PagedListHolder jest droga i tutaj jest jak:

List<String> list = // ... 

// creation 
PagedListHolder page = new PagedListHolder(list); 
page.setPageSize(10); // number of items per page 
page.setPage(0); // set to first page 

// retrieval 
page.getPageCount(); // number of pages 
page.getPageList(); // a List which represents the current page 

Jeśli trzeba sortowania, należy użyć innego PagedListHolder constructor z MutableSortDefinition .

Powiązane problemy