pringData 쿼리와 QueryDSL

김재현·2023년 12월 19일
0

TIL

목록 보기
61/88

어제에 이어 오늘은 SpringData 쿼리와 QueryDSL에 대해 공부했다.

SpringData 쿼리

SpringData 쿼리는 SprintData Common 의 CRUDRepository + PagingAndSortingRepository 이 쿼리기능을 제공한다.

쿼리명 규칙

리턴타입 {접두어}{도입부}By{프로퍼티 표현식}(조건식)[(And|Or){프로퍼티 표현식}(조건식)](OrderBy{프로퍼티}Asc|Desc) (매개변수...)

예시

// 기본
List<User> findByNameAndPassword(String name, String password);

// distinct (중복제거)
List<User> findDistinctUserByNameOrPassword(String name, String password);
List<User> findUserDistinctByNameOrPassword(String name, String password);

// ignoring case (대소문자 무시)
List<User> findByNameIgnoreCase(String name);
List<User> findByNameAndPasswordAllIgnoreCase(String name, String password);

// 정렬
List<Person> findByNameOrderByNameAsc(String name);
List<Person> findByNameOrderByNameDesc(String name);

// 페이징
Page<User> findByName(String name, Pageable pageable);  // Page 는 카운트쿼리 수행됨
Slice<User> findByName(String name, Pageable pageable); // Slice 는 카운트쿼리 수행안됨
List<User> findByName(String name, Sort sort);
List<User> findByName(String name, Pageable pageable);

// 스트림 (stream 다쓴후 자원 해제 해줘야하므로 try with resource 사용추천)
Stream<User> readAllByNameNotNull();

QueryDSL

QueryDSL의 Predicate 인터페이스로 조건문을 여러개를 구성하여 따로 관리할 수 있다.

  • findOne(Predicate), findAll(Predicate) 주로 이 2개 메소드가 사용된다.
    • findOne = Optional<T> 리턴
    • findAll = List<T> | Page<T> | Iterable<T> | Slice<T> 리턴

장점

  1. 문자가 아닌 코드로 쿼리를 작성함으로써, 컴파일 시점에 문법 오류를 쉽게 확인할 수 있다.
  2. 자동 완성 등 IDE의 도움을 받을 수 있다.
  3. 동적인 쿼리 작성이 편리하다.
  4. 쿼리 작성 시 제약 조건 등을 메서드 추출을 통해 재사용할 수 있다.

단점

  • join을 수행하지 못한다.

(Join 이 없는 대신 조건이 많은 쿼리 가능)

원리

  • QueryDSL 의존성을 추가하면 SpringData에 의해 QueryDslPredicateExecutor 인터페이스가 추가된다.
    (QueryDslPredicateExecutor는 Repository가 QueryDsl 을 실행할 수 있는 인터페이스를 제공하는 역할)

사용 방법 예시

  • QuerydslPredicateExecutor<Channel> 의존성 추가
public interface ChannelRepository extends JpaRepository<Channel, Long>,
													QuerydslPredicateExecutor<Channel> {

}
class ChannelJpaRepositoryTest {

					...
                    
  @Test
  void queryDslTest() {
    // given
    var newChannel = Channel.builder().name("teasun").build();
    channelRepository.insertChannel(newChannel);

    Predicate predicate = QChannel.channel
        .name.equalsIgnoreCase("TEASUN");

    // when
    Optional<Channel> optional = channelJpaRepository.findOne(predicate);

    // then
    assert optional.get().getName().equals(newChannel.getName());
  }
}

사실 현업에선 QuerydslPredicateExecutor가 많이 쓰이진 않는다고 한다!

내일은 실질적으로 많이 쓰이는 JPAQueryFactory 를 공부해보자.

profile
I live in Seoul, Korea, Handsome

0개의 댓글