[Springboot]쿼리메서드, 정렬과 페이징 처리

Michelle Kim·2024년 7월 9일

Springboot-Java

목록 보기
7/20

🩵쿼리 메서드 살펴보기

📍쿼리 메서드 생성

쿼리 메서드는 크게 동작을 결정하는 주제(Subject)과 서술어(Predicate)로 구분한다.
'By'는 서술어의 시작을 나타내는 구분자의 역할을 한다.
서술어 부분은 검색 및 정렬 조건을 지정하는 영역이다.
AND나 OR를 사용해 조건을 확장하는 것도 가능하다.

// (리턴타입) + {주제 + 서술어(속성)} 구조의 메서드

List<Person> findByLastnameAndEmail(String lastName, String email);

서술어에 들어가는 엔티티의 속성식은 엔티티에서 관리하고 있는 속성(필드)만 참조할 수 있다.

📍쿼리 메서드의 주제 키워드

도메인(엔티티) 표현 가능 : ...로 표시한 영역

  1. find...By
    read...By
    get...By
    query...By
    search...By
    stream...By
  2. exists...By : 특정 데이터가 존재하는지 확인 하는 키워드 (리턴 type: boolean)
  3. count...By : 조회 쿼리를 수행한 후 쿼리 결과로 나온 레코드의 개수를 리턴한다.
  4. delete...By, remove...By: 삭제 쿼리를 수행한다. 리턴타입이 없거나 삭제한 횟수를 리턴한다.
  5. ...First< number >..., ...Top< number >...: 쿼리를 통해 조회된 결괏값의 개수를 제한하는 키워드. 한번의 동작으로 여러 건을 조회할때 사용. 단 건으로 조회하기 위해서는 < number >를 생략하면 된다.

EX) 쿼리 메서드

 // find..By (예제 8.1)
    Optional<Product> findByNumber(Long number);
    List<Product> findAllByName(String name);
    Product queryByNumber(Long number);

    // exists..By (예제 8.2)
    boolean existsByNumber(Long number);

    // count..By (예제 8.3)
    long countByName(String name);

    // delete..By, remove..By (예제 8.4)
    void deleteByNumber(Long number);
    long removeByName(String name);

    // …First<number>…, …Top<number>… (예제 8.5)
    List<Product> findFirst5ByName(String name);
    List<Product> findTop10ByName(String name);

📍 쿼리 메서드의 조건자 키워드

  1. Is : 값의 일치를 조건으로 사용하는 조건자 키워드, 생략되는 경우 많음, Equals와 동일한 기능 수행
  2. (Is)Not : 값의 불일치를 조건으로 사용하는 조건자 키워드, Is생략하고 Not키워드만 사용할 수 도 있다
  3. (Is)Null, (Is)NotNull : 값이 null인지 검사하는 조건자 키워드
  4. (Is)True, (Is)False : boolean타입으로 지정된 칼럼값을 확인하는 키워드
  5. And, Or : 여러 조건을 묶을 때 사용
  6. (Is)GreaterThan, (Is)LessThan, (Is)Between : 숫자나 datetime 칼럼을 대상으로 한 비교 연산에 사용할 수 있는 조건자 키워드, 비교 대상에 대한 초과/미만의 개념으로 비교 연산 수행. 경곗값을 포함하려면 Equal키워드 추가하면 된다
  7. (Is)StartingWith(==StartsWith), (Is)EndingWith(==EndsWith), (Is)Containing(==Contains), (Is)Like : 컬럼값에서 일부 일치 여부를 확인하는 조건자 키워드, SQL쿼리문에서 '%'키워드와 동일한 역할을 한다

EX) 쿼리 메서드

 /* 쿼리 메소드의 조건자 키워드 */

    // Is, Equals (생략 가능) (예제 8.6)
    // Logical Keyword : IS , Keyword Expressions : Is, Equals, (or no keyword)
    // findByNumber 메소드와 동일하게 동작
    Product findByNumberIs(Long number);
    Product findByNumberEquals(Long number);

    // (Is)Not (예제 8.7)
    Product findByNumberIsNot(Long number);
    Product findByNumberNot(Long number);

    // (Is)Null, (Is)NotNull (예제 8.8)
    List<Product> findByUpdatedAtNull();
    List<Product> findByUpdatedAtIsNull();
    List<Product> findByUpdatedAtNotNull();
    List<Product> findByUpdatedAtIsNotNull();

    // And, Or (예제 8.10)
    Product findByNumberAndName(Long number, String name);
    Product findByNumberOrName(Long number, String name);

    // (Is)GreaterThan, (Is)LessThan, (Is)Between (예제 8.11)
    List<Product> findByPriceIsGreaterThan(Long price);
    List<Product> findByPriceGreaterThan(Long price);
    List<Product> findByPriceGreaterThanEqual(Long price);
    List<Product> findByPriceIsLessThan(Long price);
    List<Product> findByPriceLessThan(Long price);
    List<Product> findByPriceLessThanEqual(Long price);
    List<Product> findByPriceIsBetween(Long lowPrice, Long highPrice);
    List<Product> findByPriceBetween(Long lowPrice, Long highPrice);

    // (Is)Like, (Is)Containing, (Is)StartingWith, (Is)EndingWith (예제 8.12)
    List<Product> findByNameLike(String name);
    List<Product> findByNameIsLike(String name);

    List<Product> findByNameContains(String name);
    List<Product> findByNameContaining(String name);
    List<Product> findByNameIsContaining(String name);

    List<Product> findByNameStartsWith(String name);
    List<Product> findByNameStartingWith(String name);
    List<Product> findByNameIsStartingWith(String name);

    List<Product> findByNameEndsWith(String name);
    List<Product> findByNameEndingWith(String name);
    List<Product> findByNameIsEndingWith(String name);

🩵정렬과 페이징 처리

📍정렬 처리하기

기본 쿼리 메서드를 작성한 후 OrderBy키워드를 삽입하고 정렬하고자 하는 컬럼과 오름차순/내림차순을 설정하면 정렬이 수행된다.

정렬 구문은 And나 Or키워드 사용하지 않고, 우선순위를 기준으로 차례대로 작성하면 된다.

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

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

📍페이징 처리

👉 페이징이란?

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

EX) 페이징 처리위한 쿼리 메서드 예시

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

메서드 호출할때, 리턴 타입으로 Page객체 받아야한다.
Pageable파라미터를 전달하기 위해 PageRequest클래스 사용한다.
PageRequest는 Pageable의 구현체이다.

PageRequest는 of메서드를 통해 PageRequest개체를 생성한다.

EX) 페이징 쿼리 메서드를 호출하는 방법

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

getContent() : Page객체 데이터 출력
EX) Page객체의 데이터 출력

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

System.out.println(productPage.getContent());

🩵@Query어노테이션 사용하기

📍@Query 어노테이션

@Query어노테이션을 사용해 직접 JPQL을 작성할 수 있다.

EX) @Query어노테이션과 @Param어노테이션을 사용한 메서드

@Query("SELECT p FROM Product p WHERE p.name = :name")

List<Product> findByNameParam(@Param("name") String name);

@Query 를 사용하면 Entity타입이 아니라 원하는 칼럼의 값만 추출할 수 있다.

SELECT에서 가져오고자 하는 칼럼을 지정하면 된다.
이때 메서드에서는 Object배열의 리스트 형태로 리턴 타입을 지정해야 한다.

@Query("SELECT p.name, p.price, p.stock FROM Product p WHERE p.name = :name")

List<Object[]> findByNameParam2(@Param("name") String name);
profile
🇬🇧영국대학교)Computer Science학과 졸업 📚Data, AI, Backend 분야에 관심이 많습니다. 👉Email: kimbg9876@gmail.com

0개의 댓글