← Назад к вопросам

Что такое интерфейс Pageable?

2.0 Middle🔥 181 комментариев
#Docker, Kubernetes и DevOps#JVM и управление памятью

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое интерфейс Pageable

Pageable — это интерфейс Spring Data, который инкапсулирует информацию о пагинации и сортировке для запросов к базе данных. Он позволяет легко реализовать постраничную выборку данных с сортировкой, не обращаясь к деталям SQL запросов.

Основные возможности Pageable

  • Пагинация — получение определённой страницы данных
  • Сортировка — сортировка результатов по полям
  • Размер страницы — количество элементов на странице
  • Номер страницы — какую страницу получить (начиная с 0)

Структура Pageable

public interface Pageable {
    int getPageNumber();     // Номер страницы (начинается с 0)
    int getPageSize();       // Размер страницы
    long getOffset();        // Смещение (page * size)
    Sort getSort();          // Объект сортировки
    Pageable next();         // Следующая страница
    Pageable previousOrFirst(); // Предыдущая страница
}

Пример использования

import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Service;

// Entity
@Entity
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    private String name;
    private String email;
    private LocalDateTime createdAt;
    
    // Getters/Setters
}

// Repository с поддержкой Pageable
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
    Page<User> findAll(Pageable pageable);
    Page<User> findByName(String name, Pageable pageable);
}

// Service
@Service
public class UserService {
    @Autowired
    private UserRepository userRepository;
    
    // Получить первую страницу (20 элементов)
    public Page<User> getAllUsers(int page, int size, String sortBy) {
        Pageable pageable = PageRequest.of(page, size, 
            Sort.by(Sort.Direction.DESC, sortBy));
        return userRepository.findAll(pageable);
    }
}

// Controller
@RestController
@RequestMapping("/api/users")
public class UserController {
    @Autowired
    private UserService userService;
    
    @GetMapping
    public Page<User> getUsers(
        @RequestParam(defaultValue = "0") int page,
        @RequestParam(defaultValue = "20") int size,
        @RequestParam(defaultValue = "id") String sortBy) {
        return userService.getAllUsers(page, size, sortBy);
    }
}

Использование Pageable в Controller

@RestController
@RequestMapping("/api/products")
public class ProductController {
    @Autowired
    private ProductRepository productRepository;
    
    // Spring автоматически преобразует query параметры в Pageable
    @GetMapping
    public Page<Product> getAllProducts(Pageable pageable) {
        // http://localhost:8080/api/products?page=0&size=20&sort=name,desc
        return productRepository.findAll(pageable);
    }
    
    // С фильтрацией
    @GetMapping("/search")
    public Page<Product> searchProducts(
        @RequestParam String keyword,
        Pageable pageable) {
        // http://localhost:8080/api/products/search?keyword=laptop&page=0&size=10
        return productRepository.findByNameContaining(keyword, pageable);
    }
}

Создание Pageable вручную

public class PageableExamples {
    public static void main(String[] args) {
        // Пример 1: Простая пагинация
        Pageable page1 = PageRequest.of(0, 20); // Первая страница, 20 элементов
        
        // Пример 2: С сортировкой
        Pageable page2 = PageRequest.of(0, 20, 
            Sort.by("name").ascending());
        
        // Пример 3: Сортировка по нескольким полям
        Pageable page3 = PageRequest.of(0, 20, 
            Sort.by("createdAt").descending()
                .and(Sort.by("name").ascending()));
        
        // Пример 4: Сортировка с направлением
        Pageable page4 = PageRequest.of(0, 20,
            Sort.by(new Sort.Order(Sort.Direction.DESC, "createdAt"),
                    new Sort.Order(Sort.Direction.ASC, "name")));
    }
}

Работа с результатами Page<T>

public class PageResultsHandling {
    public void handleResults() {
        // Page наследует Collection и содержит дополнительную информацию
        Page<User> page = userRepository.findAll(PageRequest.of(0, 20));
        
        // Получить содержимое страницы
        List<User> users = page.getContent();
        
        // Информация о странице
        int totalPages = page.getTotalPages();        // Всего страниц
        long totalElements = page.getTotalElements(); // Всего элементов
        int pageNumber = page.getNumber();             // Номер текущей страницы
        int pageSize = page.getSize();                 // Размер страницы
        int numberOfElements = page.getNumberOfElements(); // Элементов на текущей странице
        
        // Проверки
        boolean isFirst = page.isFirst();              // Первая ли это страница
        boolean isLast = page.isLast();                // Последняя ли это страница
        boolean hasNext = page.hasNext();              // Есть ли следующая
        boolean hasPrevious = page.hasPrevious();      // Есть ли предыдущая
        
        // Навигация
        Pageable next = page.nextPageable();           // Pageable для следующей
        Pageable previous = page.previousPageable();   // Pageable для предыдущей
    }
}

Фильтрация с Pageable

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
    // Простой поиск
    Page<User> findByName(String name, Pageable pageable);
    
    // По нескольким полям
    Page<User> findByNameAndEmail(String name, String email, Pageable pageable);
    
    // С использованием Query
    @Query("SELECT u FROM User u WHERE u.createdAt >= :startDate")
    Page<User> findRecentUsers(@Param("startDate") LocalDateTime startDate, 
                               Pageable pageable);
    
    // Кастомный запрос с динамической сортировкой
    @Query("SELECT u FROM User u WHERE LOWER(u.name) LIKE LOWER(concat('%', :keyword, '%'))")
    Page<User> searchUsers(@Param("keyword") String keyword, Pageable pageable);
}

@Service
public class UserSearchService {
    @Autowired
    private UserRepository userRepository;
    
    public Page<User> searchUsers(String keyword, int page, int size) {
        Pageable pageable = PageRequest.of(page, size, 
            Sort.by(Sort.Direction.DESC, "createdAt"));
        return userRepository.searchUsers(keyword, pageable);
    }
}

REST API ответ с пагинацией

// JSON ответ выглядит так:
{
  "content": [
    {"id": 1, "name": "John", "email": "john@example.com"},
    {"id": 2, "name": "Jane", "email": "jane@example.com"}
  ],
  "pageable": {
    "pageNumber": 0,
    "pageSize": 20,
    "sort": {"unsorted": false}
  },
  "totalPages": 5,
  "totalElements": 100,
  "last": false,
  "size": 20,
  "number": 0,
  "sort": {"unsorted": false, "sorted": true, "empty": false},
  "numberOfElements": 20,
  "first": true,
  "empty": false
}

Валидация Pageable

@RestController
public class UserController {
    @GetMapping("/users")
    public Page<User> getUsers(
        @Valid Pageable pageable) {
        
        // Spring Data валидирует Pageable автоматически
        // Максимальный размер страницы: 100
        // По умолчанию: page=0, size=20
        
        return userRepository.findAll(pageable);
    }
}

// Конфигурация валидации
@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
        PageableHandlerMethodArgumentResolver resolver = 
            new PageableHandlerMethodArgumentResolver();
        resolver.setPageParameterName("page");
        resolver.setSizeParameterName("size");
        resolver.setOneIndexedParameters(false); // Нумерация с 0
        resolver.setMaxPageSize(100);
        resolver.setDefaultPageSize(20);
        resolvers.add(resolver);
    }
}

Практический пример: Поиск товаров

@RestController
@RequestMapping("/api/products")
public class ProductController {
    @Autowired
    private ProductService productService;
    
    // GET /api/products?page=0&size=20&sort=price,desc
    @GetMapping
    public ResponseEntity<Page<ProductDTO>> getProducts(
        @RequestParam(required = false) String category,
        @RequestParam(required = false) Double minPrice,
        @RequestParam(required = false) Double maxPrice,
        Pageable pageable) {
        
        Page<ProductDTO> products = 
            productService.searchProducts(category, minPrice, maxPrice, pageable);
        
        return ResponseEntity.ok(products);
    }
}

@Service
public class ProductService {
    @Autowired
    private ProductRepository productRepository;
    
    public Page<ProductDTO> searchProducts(
        String category, Double minPrice, Double maxPrice, Pageable pageable) {
        
        Page<Product> products = productRepository.findByFilters(
            category, minPrice, maxPrice, pageable);
        
        return products.map(ProductDTO::fromProduct);
    }
}

Преимущества Pageable

  1. Простота — не нужно вручную считать LIMIT и OFFSET
  2. Стандартизация — единый способ работы с пагинацией
  3. Интеграция — автоматическое преобразование query параметров
  4. Безопасность — валидация размеров страниц
  5. Гибкость — лёгкая сортировка по разным полям

Pageable — это незаменимый инструмент для работы с большими наборами данных в Spring приложениях, обеспечивая удобную и безопасную пагинацию данных.