정렬과 페이징 처리

WOOK JONG KIM·2022년 10월 31일
0
post-thumbnail

기본 쿼리 메서드인 이름을 통한 정렬과 페이징 처리도 가능하지만 다른 방법도 많이 쓰임

정렬 처리하기

일반적인 쿼리문에 정렬을 할 때는 ORDER BY 구문을 사용

// ASC : 오름차순, Desc : 내림차순
List<Product> findByNameOrderByNumberAsc(String name);
List<Product> findByNameOrderByNumberDesc(String name);

상품정보를 이름으로 검색한 후 상품 번호로 오름,내림차순 정렬을 수행한다는 뜻

정렬에서는 And나 Or 키워드를 사용하지 않고 우선순위를 기준으로 차례대로 작성

// And를 붙이지 않음
List<Product> findByNameOrderByPriceAscStockDesc(String name);

이런 쿼리 메서드의 경우 이름이 길 경우 가독성이 떨어짐
-> 매개변수를 활용해 정렬할 수도 있음

밑의 부분을 Test가 아닌 ProductRepository 인터페이스에 넣어야 함

List<Product> findByName(String name, Sort sort);

이때는 이름을 키워드로 넣지 않고 Sort 객체를 활용해 매개변수로 받아들인 정렬 기준을 가지고 쿼리문을 자동작성하게 됨

@SpringBootTest
public class ProductRepositoryTest {

    @Autowired
    ProductRepository productRepository;

    @Test
    void sortingAndPagingTest(){
        Product product1 = new Product();
        product1.setName("펜");
        product1.setPrice(1000);
        product1.setStock(100);
        product1.setCreatedAt(LocalDateTime.now());
        product1.setUpdatedAt(LocalDateTime.now());

        Product product2 = new Product();
        product2.setName("펜");
        product2.setPrice(5000);
        product2.setStock(300);
        product2.setCreatedAt(LocalDateTime.now());
        product2.setUpdatedAt(LocalDateTime.now());

        Product product3 = new Product();
        product3.setName("펜");
        product3.setPrice(500);
        product3.setStock(50);
        product3.setCreatedAt(LocalDateTime.now());
        product3.setUpdatedAt(LocalDateTime.now());

        Product savedProduct1 = productRepository.save(product1);
        Product savedProduct2 = productRepository.save(product2);
        Product savedProduct3 = productRepository.save(product3);

        productRepository.findByName("펜", Sort.by(Order.asc("price")));
        productRepository.findByName("펜", Sort.by(Order.asc("price"), Sort.Order.desc("stock")));
    }
}

밑의 2줄 코드를 통해 메서드에 전달함

Hibernate: 
    select
        product0_.number as number1_0_,
        product0_.created_at as created_2_0_,
        product0_.name as name3_0_,
        product0_.price as price4_0_,
        product0_.stock as stock5_0_,
        product0_.updated_at as updated_6_0_ 
    from
        product product0_ 
    where
        product0_.name=? 
    order by
        product0_.price asc
        
Hibernate: 
    select
        product0_.number as number1_0_,
        product0_.created_at as created_2_0_,
        product0_.name as name3_0_,
        product0_.price as price4_0_,
        product0_.stock as stock5_0_,
        product0_.updated_at as updated_6_0_ 
    from
        product product0_ 
    where
        product0_.name=? 
    order by
        product0_.price asc,
        product0_.stock desc

매개변수를 활용한 쿼리 메서드 사용 시 쿼리 메서드를 정의하는 단계에서 코드가 줄어들지만 호출하는 위치에서는 여전히 정렬 기준이 길어져 가독성이 어렵다

Sort 부분을 하나의 메서드로 분리해서 쿼리 메서드를 호출하는 코드를 작성하기도 함

private Sort getSort(){
	return Sort.by{
    	Order.asc("price")
        Order.desc("stock")
    };
}

페이징 처리

페이징이란 데이터베이스의 레코드를 개수로 나눠 페이지를 구분하는 것

ex) 25개의 레코드가 있다면 레코드를 7개씩, 총 4개의 페이지를 구분하고 그중에서 특정 페이지를 가져오는 것

JPA에서는 페이징 처리를 위해 Page와 Pageable을 사용

productRepository

Page<Product> findByName(String name, Pageable pageable);

리턴 타입으로 Page를 설정하고, 매개변수에는 Pageable 타입의 객체를 의미

test/productRepositoryTest

Page<Product> productPage = productRepository.findByName("펜", PageRequest.of(0,2));

Pageable 파라미터를 전달 하기 위해 PageRequest(Pageable 구현체) 사용

PageRequest는 of 메서드를 통해 PageRequest 객체 생성 -> 다양한 형태로 오버로딩 되었음

of(int page, int size)
of(int page, int size, Sort)
of(int page, int size, Direction, String properties)

위 코드 실행 결과

Hibernate: 
    select
        product0_.number as number1_0_,
        product0_.created_at as created_2_0_,
        product0_.name as name3_0_,
        product0_.price as price4_0_,
        product0_.stock as stock5_0_,
        product0_.updated_at as updated_6_0_ 
    from
        product product0_ 
    where
        product0_.name=? limit ?
Hibernate: 
    select
        count(product0_.number) as col_0_0_ 
    from
        product product0_ 
    where
        product0_.name=?

select 쿼리에 limit 쿼리가 포함되어있음

만약 페이지번호를 0 아닌 1이상의 숫자로 설정하면 offset 키워드도 포함되어 레코드 목록을 구분해서 가져옴

페이지 객체 그냥 출력시

-> 값을 보여주지 않고 몇 번째 페이지에 해당하는지 확인 가능

System.out.println(productPage);

Page 1 of 2 containing com.springboot.advanced_jpa.data.entity.Product instances

getContent() 메서드를 활용하면 배열 형태로 값이 출력

System.out.pirntln(productPage.getContent());
profile
Journey for Backend Developer

0개의 댓글