빙응의 공부 블로그
[Spring]QueryDSL에 대해 알아보자! 본문
📝 QueryDSL은 무엇일까요?
DSL은 Domain Specific Language의 약자로, 특정 영역에 특화된 언어를 의미한다.
즉 QueryDSL은 쿼리생성에 특화된 프레임워크를 의미한다.
그렇다면 QueryDSL이 필요한 이유가 무엇일까???
스프링의 JPA는 객체지향 어플리케이션과 관계형 DB 사이의 패러다임 불일치를 해결하는 프레임워크이다.
개발자는 객체지향 관점으로 개발하고 JPA는 자동으로 SQL쿼리문을 생성한다. 그렇기에 개발자는 SQL 관점에서
프로그래밍을 하지 않아도 된다. 그러나 완전한 분리는 불가능해 JPA는 JPQL을 지원한다.
public interface EmployeeRepository extends JpaRepository<Employee, Long> {
// JPQL 쿼리 사용
@Query("SELECT e FROM Employee e WHERE e.salary > :salary")
List<Employee> findEmployeesWithSalaryGreaterThan(@Param("salary") Double salary);
// 네이티브 SQL 쿼리 사용
@Query(value = "SELECT * FROM Employee WHERE salary > :salary", nativeQuery = true)
List<Employee> findEmployeesWithSalaryGreaterThanNative(@Param("salary") Double salary);
}
완전히 분리가 불가능한 것은 알겠는데 JPQL이 어때서??
JPQL은 SQL문과 상당히 유사하다. 객체지향 관점을 유지하는 SQL문이라고 보면 된다.
그러나 여기에 큰 문제 2가지가 생긴다.
📌1. 타입안정성이 떨어진다.
JPQL은 문자열 취급이기에 JPQL 문법이 틀려도 실제 실행해보는 것이 아닌 이상 문제를 알아차릴 수 없다.
결국 프로그램을 실행해야만 문제를 발견할 수 있다는 것이다. 한마디로 타입 안정성이 떨어지는 것
📌2. 직관적인 동적쿼리 작성이 어렵다.
// JPQL 쿼리 사용
@Query("SELECT e FROM Employee e WHERE e.salary > :salary")
List<Employee> findEmployeesWithSalaryGreaterThan(@Param("salary") Double salary);
// 네이티브 SQL 쿼리 사용
@Query(value = "SELECT * FROM Employee WHERE salary > :salary", nativeQuery = true)
List<Employee> findEmployeesWithSalaryGreaterThanNative(@Param("salary") Double salary)
자 위 쿼리들을 자세히 봐보자 처음으로든 생각은 아마 가독성이 떨어진다는 것이다.
JPQL는 직접 입력이기에 가독성이 매우 떨어진다. 물론 볼 수는 있으나 복잡한 쿼리는 집중하고 해부해야한다.
📝QueryDSL의 장점
📌 JPQL
JPQL는 사용자가 직접 입력하여 EntityManager에 접근한다.
📌QueryDSL
QueryDSL은 사용자가 직접 설정한 것을 이용하여 JPQL을 생성한다. 이 과정을 통해 JPQL의 문제를 고친다.
@Test
public void startJPQL() {
//member1을 찾아라.
String qlString =
"select m from Member m " +
"where m.username = :username";
Member findMember = em.createQuery(qlString, Member.class)
.setParameter("username", "member1")
.getSingleResult();
Assertions.assertThat(findMember.getUsername()).isEqualTo("member1");
}
@Test
public void startQuerydsl() {
//member1을 찾아라.
QMember m = new QMember("m");
Member findMember = queryFactory
.select(m)
.from(m)
.where(m.username.eq("member1"))//파라미터 바인딩 처리
.fetchOne();
Assertions.assertThat(findMember.getUsername()).isEqualTo("member1");
}
QueryDSL의 목적은 JPQL의 동적 생성이다.
개발자는 QueryDSL을 통해 JPQL을 쉽게 가독성이 좋게, 안정적으로 생성할 수 있다.
📌Q타입
개발자가 QueryDSL이 JPQL 생성할 수 있도록 할때 Entity 정보가 필요하다.
이것이 바로 Q타입 클래스로 Entity 정보를 담는 것이다.
Q타입클래스는 QueryDSL 플러그인으로 컴파일하면 지정된 위치에 생성된다.
개발자는 Q타입 객체를 생성하여 JPQL 생성에 필요한 데이터를 QueryDSL로 넘길 수 있다.
QueryDSL 작성 예시
@Test
public void startQuerydsl() {
//member1을 찾아라.
QMember m = new QMember("m");
Member findMember = queryFactory
.select(m)
.from(m)
.where(m.username.eq("member1"))//파라미터 바인딩 처리
.fetchOne();
Assertions.assertThat(findMember.getUsername()).isEqualTo("member1");
}
import static study.querydsl.entity.QMember.*;
@Test
public void startQuerydsl3() {
//member1을 찾아라.
Member findMember = queryFactory
.select(member)
.from(member)
.where(member.username.eq("member1"))
.fetchOne();
assertThat(findMember.getUsername()).isEqualTo("member1");
}
✔ 정리
QueryDSL은 JPQL 생성용 데이터 세팅 장치이다.
QueryDSL은 데이터 세팅에 특횐 디자인 패턴인 빌더 패턴으로 이루어져 있다.
이 패턴을 통해 미리 JPQL을 설정해 동적 생성이 가능해진다.
가장 중요한 데이터는 Q타입클래스를 객체로 전달하여 JPQL에서 필요한 Entity 정보를 제공한다.
- QueryDSL이란?
- QueryDSL은 JPQL(또는 SQL) 쿼리를 타입 안전하게 작성하기 위한 라이브러리이다. 이를 통해 런타임 시 발생할 수 있는 쿼리 오류를 컴파일 타임에 잡을 수 있다..
- 빌더 패턴 사용:
- QueryDSL은 빌더 패턴을 사용하여 쿼리를 구성한다.. 빌더 패턴을 사용하면 쿼리를 단계별로 쉽게 작성하고 읽기 쉽게 만들 수 있다.
- Q 타입 클래스:
- QueryDSL의 핵심은 Q 타입 클래스이다. Q 타입 클래스는 엔티티 클래스를 기반으로 생성되며, 해당 엔티티의 속성에 접근할 수 있는 정적 메타데이터를 제공한다.
- 예를 들어, Member 엔티티가 있을 때 QMember 클래스가 생성된다.. 이 클래스는 Member 엔티티의 속성에 접근할 수 있는 필드를 포함한다.
- QMember.member와 같은 방식으로 사용된다.
- 동적 쿼리 생성:
- QueryDSL을 사용하면 조건에 따라 동적으로 쿼리를 생성할 수 있다. 예를 들어, 검색 조건이 여러 개일 때 조건에 따라 쿼리를 유연하게 조립할 수 있다.
🧷 참고 자료
실전! Querydsl 강의 | 대시보드 - 인프런 (inflearn.com)
'Spring > QueryDSL' 카테고리의 다른 글
[Spring]QueryDSL 중급 문법 (0) | 2024.07.29 |
---|---|
[Spring]QueryDSL 기본문법 (0) | 2024.07.28 |