[Spring JPA] QueryDsl이란?

SangYu Lee·2023년 2월 20일
1

QueryDsl이 뭘까

Querydsl은 HQL(Hibernate Query Language) 쿼리를 타입에 안전하게 생성 및 관리할 수 있게 해주는 프레임워크이며 자바 코드 기반으로 쿼리를 작성하게 해준다

QueryDsl 쓰는 이유

SQL문을 작성하지 않아도 JPA Query Method를 통해 간단한 데이터 베이스 조회가 가능하다.

email을 통해 회원을 조회하는 query method인데, 이처럼 JPA Query Method를 사용하면 간단한 조회는 상관없지만 복잡할 경우에는 몇 가지 문제가 있다.

1. 직접적인 연관관계가 없는 entity의 join이 어렵다

A -> B -> C 의 순서로 OneToMany 연관관계를 가지는 구조에서

특정 조건의 Entity C를 가지는 Entity A를 JPA Query Method를 사용한 repository에서는 검색이 불가능하다. 직접적으로 Entity A 내부의 Entity B 내부의 Entity C로 들어가서 찾는 경우에는 가능하지만 연관된 모든 entity를 불러오고, 조건에 맞는 반복문과 비교문을 사용해야 하기 때문에 성능이 나쁘다.

2. entity의 원하는 필드만 가져올 수 없다.

Entity A와 Entity B에서 member필드 값만 필요하다고 해도 Entity의 모든 필드를 조회한 후에 따로 ResponseDto를 만들어서 반환해야 한다.

3. 복잡한 SQL문

이건 @Query를 이용한 nativeQuery나 JPQL을 사용했을 때 발생하는데
사실 sql문 사용 자체는 복잡해도 필요하면 써야지 어쩔 수 없다.

@Query("select p from Post p join fetch p.user u "
    + "where u in "
    + "(select t from Follow f inner join f.target t on f.source = :user) "
    + "or u = :user "
    + "order by p .createdAt desc")
List<Post> findAllAssociatedPostsByUser(@Param("user") User user, Pageable pageable);

문제는 문법을 잘못 작성하였다면 서버를 돌리고 나서 런타임 시점에 알 수 있다.
컴퓨터가 빠르더라도 컴파일 시점에 문법 오류를 잡는 것이 속도가 더 빠르며, 또 이러한 복잡한 SQL을 익숙한 자바 코드로 작성할 수 있다는 점이 queryDsl의 가장 큰 장점이다.

<QueryDsl 사용예제>

QueryDsl 장점과 단점

Query Dsl의 장점을 정리하면

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

Query Dsl의 단점

  1. 초기 세팅이 좀 어렵다
  2. JPA 1차 캐시 사용이 불가능하다

JPA 1차 캐시 사용이 불가능한 이유는

QueryDsl은 기본적으로 "JPQL을 java코드로 쓸 수 있게 해주는" JPQL 빌더이다. JPQL은 SQL문으로 번역되어서 우선적으로 DB에 다이렉트로 select문을 쏜다. 기본적으로 JPA를 사용하여 Select를 하게되면 영속성 컨텍스트 1차 캐시에 데이터가 저장이되는데, QueryDsl은 이를 무시하고 DB에서 직접적으로 조회해온다.

여기서 문제가 발생하는 경우도 있다.

영속성 컨텍스트에 이미 존재하는 객체와 DB에서 조회해온 객체 아이디가 같을 경우 1차 캐시에 존재하는 데이터를 사용한다.

예를 들어서 모든 회원의 이름이 john이고 JPA로 모든 회원을 한번 조회했다고 했을 때, 영속성 컨텍스트 1차 캐시에 모든 회원의 이름이 john으로 저장되어 있을 것이다. 이 상황에서 QueryDsl로 회원의 이름을 전부 simpson으로 바꿔도 JPA로 조회를 한다면 JPA 1차 캐시에 존재하는 회원(이름이 john)의 데이터를 반환하기 때문에 모든 회원의 이름이 john으로 나올 것이다.

Reference
https://kukekyakya.tistory.com/9?category=1022639
https://blog.naver.com/PostView.naver?blogId=innogrid&logNo=222725730056&parentCategoryNo=&categoryNo=12&viewDate=&isShowPopularPosts=true&from=search
https://tecoble.techcourse.co.kr/post/2021-08-08-basic-querydsl/
https://www.inflearn.com/chats/669477/querydsl-springboot-2-7%EC%9D%98-gradle-%EC%84%A4%EC%A0%95%EC%9D%84-%EA%B3%B5%EC%9C%A0%ED%95%A9%EB%8B%88%EB%8B%A4
https://velog.io/@dkajffkem/1%EC%B0%A8-%EC%BA%90%EC%8B%9C-%EB%8D%B0%EC%9D%B4%ED%84%B0-vs-DB-%EB%8D%B0%EC%9D%B4%ED%84%B0
https://chilling.tistory.com/49
https://cobbybb.tistory.com/18
https://devocean.sk.com/blog/techBoardDetail.do?ID=163915
https://jddng.tistory.com/345
https://techblog.woowahan.com/2600/
http://querydsl.com/static/querydsl/4.4.0/apidocs/
https://stackoverflow.com/questions/60021815/why-has-javax-persistence-api-been-replaced-by-jakarta-persistence-api-in-spring

profile
아이스커피

1개의 댓글

comment-user-thumbnail
2023년 2월 21일

실제 개발하면서 queryDsl을 알았다면이란 생각이 드네요..
또, QueryDsl을 잘 몰랐는데 "JPQL을 java코드로 쓸 수 있게 해주는JPQL 빌더"란 말이 확 와닿게 오네요!
JPA와의 장단점도 잘 정리되어 있어서 좋았습니다!

답글 달기