[실전! 스프링 데이터 JPA] 다양한 쿼리 작성 도구 (Specifications, Query By Example, Projections, Native Query 👉 QueryDSL)

강신현·2022년 8월 12일
0

✅ JPA Criteria ✅ jpql ✅ Querydsl


💡 Specifications

AND OR 같은 연산자로 조합해서 다양한 검색조건을 쉽게 생성(컴포지트 패턴)
스프링 데이터 JPA는 JPA Criteria를 활용해서 이 개념을 사용할 수 있도록 지원

👉 너무 복잡해서 실무에서는 JPA Criteria를 거의 안쓰고 대신에 QueryDSL을 사용한다.


💡 Query By Example

https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#query-by-example

필드 이름이 포함된 쿼리를 작성할 필요가 없이 도메인 객체 (entity) 를 그대로 가지고 검색 조건을 만든다.

👉 매칭 조건이 너무 단순하고, INNER 조인만 되고 LEFT 조인이 안되기 때문에 실무에서는 QueryDSL을 사용한다.


💡 Projections

엔티티 대신에 DTO를 편리하게 조회할 때 사용

ex : 전체 엔티티가 아니라 회원 이름만 딱 조회하는 경우

👉 프로젝션 대상이 root 엔티티를 넘어가면 JPQL SELECT 최적화가 안되고 복잡한 쿼리를 해결하기에는 한계가 있기 때문에
실무에서는 단순할 때만 사용하고, 조금만 복잡해지면 QueryDSL을 사용한다.


💡 Native Query

가급적 네이티브 쿼리는 사용하지 않는게 좋지만 정말 어쩔 수 없을 때 사용한다.
최근에 나온 스프링 데이터 Projections 활용하는 것이 좋다.

  • JPQL은 위치 기반 파리미터를 1부터 시작하지만 네이티브 SQL은 0부터 시작
  • 페이징 지원
  • 반환 타입
    • Object[]
    • Tuple
    • DTO(스프링 데이터 인터페이스 Projections 활용, JdbcTemplate or myBatis 권장)
  • 제약
    • Sort 파라미터를 통한 정렬이 정상 동작하지 않을 수 있음(믿지 말고 직접 처리)
    • JPQL처럼 애플리케이션 로딩 시점에 문법 확인 불가
    • 동적 쿼리 불가

구현

  • MemberProjection
public interface MemberProjection {
    Long getId();
    String geUserName();
    String getTeamName();
}
  • MemberRepository
@Query(value = "SELECT m.member_id as id, m.username, t.name as teamName "
            + "FROM member m left join team t",
            countQuery = "SELECT count(*) from member",
            nativeQuery = true)
Page<MemberProjection> findByNativeProjection(Pageable pageable);

이처럼 정적 네이티브 쿼리를 페이징 처리까지 할 수 있지만 동적 쿼리는 불가능하다.


동적 네이티브 쿼리는 두가지 방법으로 구현 가능하다.
1. 하이버네이트를 직접 활용

String sql = "select m.username as username from member m";
List<MemberDto> result = em.createNativeQuery(sql)
        .setFirstResult(0)
        .setMaxResults(10)
        .unwrap(NativeQuery.class)
        .addScalar("username")
        .setResultTransformer(Transformers.aliasToBean(MemberDto.class))
        .getResultList();
}
  1. 스프링 JdbcTemplate, myBatis, jooq같은 외부 라이브러리 사용

💡 jpql vs Querydsl

그래서 jpql이 좋은지 Querydsl 좋은지 고민이 되어 찾아보니 같은 질문을 한 사람이 있어 퍼옴

https://www.inflearn.com/questions/38771

결론은

  • 동적쿼리 : Querydsl
    👉 커스텀 레포지토리 만들어서 처리
  • 단순한 정적쿼리 몇개만 필요한 경우 : jpql
    👉 @Query로 인터페이스에서 처리


강의 출처

[인프런 - 김영한] 실전! 스프링 데이터 JPA

profile
땅콩의 모험 (server)

0개의 댓글