Spring Data cung cấp Pageable + PageRequest cho pagination và Sort cho sorting.
java
// Repository
public interface UserRepository extends JpaRepository<User, Long> {
Page<User> findByActive(boolean active, Pageable pageable);
List<User> findByRole(String role, Sort sort);
}
// Service
@Service
class UserService {
public Page<User> getActiveUsers(int page, int size, String sortBy) {
Pageable pageable = PageRequest.of(
page, // 0-indexed
size,
Sort.by(sortBy).descending()
);
return userRepo.findByActive(true, pageable);
}
public List<User> getAdminsByName() {
Sort sort = Sort.by(
Sort.Order.asc("lastName"),
Sort.Order.asc("firstName")
);
return userRepo.findByRole("ADMIN", sort);
}
}
// Controller
@GetMapping("/users")
Page<UserDTO> list(
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "20") int size,
@RequestParam(defaultValue = "createdAt") String sort
) {
return userService.getActiveUsers(page, size, sort)
.map(userMapper::toDTO); // map sang DTO
}Page response có:
json
{
"content": [...],
"totalElements": 100,
"totalPages": 5,
"size": 20,
"number": 0, // current page
"first": true,
"last": false
}Lưu ý: không dùng findAll(Pageable) trực tiếp với large table — count query bổ sung.
Dùng Slice<T> khi không cần totalElements (infinite scroll).
Spring Data provides Pageable + PageRequest for pagination and Sort for sorting.
java
// Repository
public interface UserRepository extends JpaRepository<User, Long> {
Page<User> findByActive(boolean active, Pageable pageable);
List<User> findByRole(String role, Sort sort);
}
// Service
@Service
class UserService {
public Page<User> getActiveUsers(int page, int size, String sortBy) {
Pageable pageable = PageRequest.of(
page, // 0-indexed
size,
Sort.by(sortBy).descending()
);
return userRepo.findByActive(true, pageable);
}
}
// Controller
@GetMapping("/users")
Page<UserDTO> list(
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "20") int size,
@RequestParam(defaultValue = "createdAt") String sort
) {
return userService.getActiveUsers(page, size, sort)
.map(userMapper::toDTO);
}Page response includes:
json
{
"content": [...],
"totalElements": 100,
"totalPages": 5,
"size": 20,
"number": 0, // current page
"first": true,
"last": false
}Note: avoid findAll(Pageable) on large tables — it adds an extra count query.
Use Slice<T> when totalElements is not needed (infinite scroll).