Seitennummerierung, Sortierung und Projektionen
Geben Sie paginierte Ergebnisse mit Pageable zurück, sortieren Sie dynamisch und verwenden Sie Interface-Projektionen, um die abgerufenen Spalten zu begrenzen.
Seitennummerierung, Sortierung und Projektionen ist eine kostenlose Java Academy-Lektion auf CoddyKit. Dies ist Lektion 4 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des Java Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Java Academy-Kurs umfasst insgesamt 4 Lektionen.
Warum Pagination?
Tausende Zeilen in einer einzigen Abfrage zurückzugeben, verschwendet Speicher und Bandbreite. Pagination lädt jeweils nur eine Seite. Spring Data integriert Pagination über die Abstraktion Pageable.
Pageable und PageRequest
Erstellen Sie ein Pageable mit PageRequest.of(page, size). Übergeben Sie es an jede Repository-Methode, die ein Page<T> zurückgibt.
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());Sortierung mit PageRequest
Fügen Sie PageRequest mit einem Sort-Objekt eine Sortierung hinzu. Verketten Sie mehrere Felder mit 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> führt eine COUNT-Abfrage aus, um die Gesamtzahl der Seiten zu berechnen. Slice<T> tut dies nicht – es weiß nur, ob eine nächste Seite vorhanden ist. Verwenden Sie Slice für Infinite Scrolling, wenn die Gesamtanzahl nicht benötigt wird.
public interface UserRepository extends JpaRepository<User, Long> {
Slice<User> findByStatus(UserStatus status, Pageable pageable);
}Integration in Spring MVC
Spring MVC löst Pageable automatisch aus Query-Parametern auf: ?page=0&size=20&sort=name,asc. Eine manuelle Auswertung ist nicht erforderlich.
@GetMapping("/users")
public Page<UserDto> list(Pageable pageable) {
return userRepo.findAll(pageable).map(UserDto::from);
}
// GET /users?page=0&size=10&sort=name,ascInterface-Projections
Definieren Sie ein Interface mit Getter-Methoden, deren Namen den Feldnamen der Entität entsprechen. Spring Data gibt nur diese Spalten zurück – dadurch werden die übertragenen Daten reduziert und interne Details verborgen.
public interface UserSummary {
Long getId();
String getName();
String getEmail();
}
List<UserSummary> findByStatus(UserStatus status);Klassenbasierte (DTO-)Projections
Verwenden Sie ein DTO-Record oder eine DTO-Klasse mit einem Konstruktor. Spring Data erzeugt für die ausgewählten Spalten automatisch einen JPQL-Konstruktorausdruck.
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);Dynamische Projections
Übergeben Sie den Projection-Typ als generischen Parameter an die Repository-Methode, um die Projection beim Aufruf auszuwählen.
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);Keyset-Pagination (Offset vs. Keyset)
Offset-Pagination (OFFSET N) wird bei großen Offsets zunehmend langsamer. Keyset-Pagination (mit WHERE id > lastSeenId) hat unabhängig von der Seitentiefe eine Komplexität von O(1) und eignet sich daher besser für tiefe Pagination.
// 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);Optimierung der Gesamtanzahl
Verwenden Sie countQuery in @Query, um eine optimierte Count-Abfrage bereitzustellen, die teure JOINs in der Hauptabfrage vermeidet.
@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);ResponseEntity mit Seitenmetadaten zurückgeben
Nehmen Sie Seitenmetadaten (totalElements, totalPages, number, size) in die REST-Antwort auf, damit Clients wissen, wie sie durch die Seiten navigieren können.
@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()
));
}Kurze Überprüfung
Was ist der wichtigste Unterschied zwischen Page und Slice?
Zusammenfassung
Verwenden Sie Pageable+PageRequest.of() für Offset-Pagination. Spring MVC löst Pageable aus Query-Parametern auf. Verwenden Sie Slice, um die COUNT-Abfrage zu vermeiden. Verwenden Sie Interface- oder DTO-Projections, um die abgerufenen Spalten zu begrenzen. Setzen Sie bei großen Offsets auf Keyset-Pagination.
Häufig gestellte Fragen
Ist die Lektion „Seitennummerierung, Sortierung und Projektionen“ kostenlos?
Ja — der vollständige Text von „Seitennummerierung, Sortierung und Projektionen“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des Java Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Java Academy-Kurs umfasst insgesamt 4 Lektionen.
Was lerne ich in „Seitennummerierung, Sortierung und Projektionen“?
Geben Sie paginierte Ergebnisse mit Pageable zurück, sortieren Sie dynamisch und verwenden Sie Interface-Projektionen, um die abgerufenen Spalten zu begrenzen. Du übst Java Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.
Brauche ich Erfahrung, um Java Academy zu starten?
Keine Vorkenntnisse erforderlich. Java Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 4 von 4.
Wie lange dauert die Lektion „Seitennummerierung, Sortierung und Projektionen“?
Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.
Kann ich in dieser Java Academy-Lektion Code schreiben und ausführen?
Ja. Jede Java Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.
Alle Lektionen in diesem Kurs
- Entity-Mapping mit JPA-Annotationen
- Spring-Data-Repositories und Abfragemethoden
- One-to-Many- und Many-to-Many-Beziehungen
- Seitennummerierung, Sortierung und Projektionen