Paginação, ordenação e projeções
Retorne resultados paginados com Pageable, ordene dinamicamente e use projeções de interface para limitar as colunas buscadas.
Paginação, ordenação e projeções é uma aula grátis de Java Academy no CoddyKit. Esta é a aula 4 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Java Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Java Academy inclui 4 aulas no total.
Por que usar paginação?
Retornar milhares de linhas em uma única consulta desperdiça memória e largura de banda. A paginação carrega uma página por vez. O Spring Data integra a paginação por meio da abstração Pageable.
Pageable e PageRequest
Crie um Pageable usando PageRequest.of(page, size). Passe-o para qualquer método de repositório que retorne Page<T>.
Pageable pageable = PageRequest.of(0, 20); // page 0, 20 per page
Page<User> page = userRepo.findAll(pageable);
System.out.println("Total: " + page.getTotalElements());
System.out.println("Pages: " + page.getTotalPages());
System.out.println("Content: " + page.getContent().size());Ordenação com PageRequest
Adicione ordenação a PageRequest com um objeto Sort. Encadeie vários campos com Sort.by().and().
Pageable sorted = PageRequest.of(0, 20,
Sort.by(Sort.Direction.DESC, "createdAt")
.and(Sort.by("name")));
Page<User> page = userRepo.findAll(sorted);Slice vs Page
Page<T> executa uma consulta COUNT para calcular o total de páginas. Slice<T> não executa essa consulta — ele apenas sabe se existe uma próxima página. Use Slice para rolagem infinita quando a contagem total não for necessária.
public interface UserRepository extends JpaRepository<User, Long> {
Slice<User> findByStatus(UserStatus status, Pageable pageable);
}Integração com Spring MVC
O Spring MVC resolve automaticamente Pageable a partir dos parâmetros da consulta: ?page=0&size=20&sort=name,asc. Não é necessário fazer a análise manualmente.
@GetMapping("/users")
public Page<UserDto> list(Pageable pageable) {
return userRepo.findAll(pageable).map(UserDto::from);
}
// GET /users?page=0&size=10&sort=name,ascProjeções com interfaces
Defina uma interface com métodos getter correspondentes aos nomes dos campos da entidade. O Spring Data retorna apenas essas colunas — reduzindo a transferência de dados e ocultando detalhes internos.
public interface UserSummary {
Long getId();
String getName();
String getEmail();
}
List<UserSummary> findByStatus(UserStatus status);Projeções baseadas em classe (DTO)
Use um record ou uma classe DTO com um construtor. O Spring Data gera uma expressão de construtor JPQL para as colunas selecionadas.
public record UserDto(Long id, String name, String email) {}
@Query("SELECT new com.example.UserDto(u.id, u.name, u.email) FROM User u WHERE u.status = :s")
List<UserDto> findSummaries(@Param("s") UserStatus status);Projeções dinâmicas
Passe o tipo da projeção como parâmetro genérico para o método do repositório e escolha a projeção no local da chamada.
public interface UserRepository extends JpaRepository<User, Long> {
<T> List<T> findByStatus(UserStatus status, Class<T> type);
}
// Usage:
List<UserSummary> summaries = repo.findByStatus(ACTIVE, UserSummary.class);
List<User> full = repo.findByStatus(ACTIVE, User.class);Paginação por chave (deslocamento vs. chave)
A paginação por deslocamento (OFFSET N) fica mais lenta com deslocamentos grandes. A paginação por chave (usando WHERE id > lastSeenId) é O(1), independentemente da profundidade da página — sendo melhor para paginações profundas.
// Keyset pagination:
@Query("SELECT u FROM User u WHERE u.id > :lastId ORDER BY u.id LIMIT :size")
List<User> findPage(@Param("lastId") Long lastId, @Param("size") int size);Otimização da contagem total
Use countQuery em @Query para fornecer uma consulta de contagem otimizada que evite JOINs dispendiosos na consulta principal.
@Query(value = "SELECT u FROM User u JOIN FETCH u.orders WHERE u.status = :s",
countQuery = "SELECT COUNT(u) FROM User u WHERE u.status = :s")
Page<User> findActiveWithOrders(@Param("s") UserStatus s, Pageable p);Retornando ResponseEntity com metadados da página
Inclua os metadados da página (totalElements, totalPages, número, tamanho) na resposta REST para que os clientes saibam como navegar.
@GetMapping("/users")
public ResponseEntity<Map<String, Object>> list(Pageable p) {
Page<UserDto> page = repo.findAll(p).map(UserDto::from);
return ResponseEntity.ok(Map.of(
"content", page.getContent(),
"totalElements", page.getTotalElements(),
"totalPages", page.getTotalPages()
));
}Verificação rápida
Qual é a principal diferença entre Page e Slice?
Recapitulação
Use Pageable+PageRequest.of() para paginação por deslocamento. O Spring MVC resolve Pageable a partir dos parâmetros da consulta. Use Slice para evitar COUNT. Use projeções com interfaces ou DTOs para limitar as colunas carregadas. Use paginação por chave para deslocamentos grandes.
Perguntas Frequentes
A aula “Paginação, ordenação e projeções” é grátis?
Sim — o texto completo de “Paginação, ordenação e projeções” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Java Academy, atualize para CoddyKit PRO. O curso de Java Academy inclui 4 aulas no total.
O que vou aprender em “Paginação, ordenação e projeções”?
Retorne resultados paginados com Pageable, ordene dinamicamente e use projeções de interface para limitar as colunas buscadas. Você pratica Java Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar Java Academy?
Nenhuma experiência prévia é necessária. Java Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 4 de 4.
Quanto tempo leva a aula “Paginação, ordenação e projeções”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de Java Academy?
Sim. Cada aula de Java Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Mapeamento de entidades com anotações JPA
- Repositórios do Spring Data e métodos de consulta
- Relacionamentos um-para-muitos e muitos-para-muitos
- Paginação, ordenação e projeções