✅ JPA Criteria ✅ jpql ✅ Querydsl
AND OR 같은 연산자로 조합해서 다양한 검색조건을 쉽게 생성(컴포지트 패턴)
스프링 데이터 JPA는 JPA Criteria를 활용해서 이 개념을 사용할 수 있도록 지원
👉 너무 복잡해서 실무에서는 JPA Criteria를 거의 안쓰고 대신에 QueryDSL을 사용한다.
https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#query-by-example
필드 이름이 포함된 쿼리를 작성할 필요가 없이 도메인 객체 (entity) 를 그대로 가지고 검색 조건을 만든다.
👉 매칭 조건이 너무 단순하고, INNER 조인만 되고 LEFT 조인이 안되기 때문에 실무에서는 QueryDSL을 사용한다.
엔티티 대신에 DTO를 편리하게 조회할 때 사용
ex : 전체 엔티티가 아니라 회원 이름만 딱 조회하는 경우
👉 프로젝션 대상이 root 엔티티를 넘어가면 JPQL SELECT 최적화가 안되고 복잡한 쿼리를 해결하기에는 한계가 있기 때문에
실무에서는 단순할 때만 사용하고, 조금만 복잡해지면 QueryDSL을 사용한다.
가급적 네이티브 쿼리는 사용하지 않는게 좋지만 정말 어쩔 수 없을 때 사용한다.
최근에 나온 스프링 데이터 Projections 활용하는 것이 좋다.
public interface MemberProjection {
Long getId();
String geUserName();
String getTeamName();
}
@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();
}
그래서 jpql이 좋은지 Querydsl 좋은지 고민이 되어 찾아보니 같은 질문을 한 사람이 있어 퍼옴
https://www.inflearn.com/questions/38771
결론은
- 동적쿼리 :
Querydsl
👉 커스텀 레포지토리 만들어서 처리- 단순한 정적쿼리 몇개만 필요한 경우 :
jpql
👉 @Query로 인터페이스에서 처리