[Java]Query DSL 기초

코딩하는 개구리·2023년 9월 13일
0

[Java]

목록 보기
1/2

원래 하던 프로젝트를 그만두고 다른 프로젝트에 중간에 참여하게 되었다.
프로젝트 온보딩을 하는 과정에서 QueryDSL이 구현된 부분이 있었고, 그 부분을 나름 코드만 보고 이해했었다고 생각했지만, 내 착각이었다.. 그래서 QueryDSL에 대한 기초를 알아보고자 한다!

QueryDLS 이란?

QueryDSL은 Java 언어를 기반으로 데이터베이스 쿼리를 생성하는 데 사용되는 도메인 특화 언어이다.
이것은 데이터베이스와 상호 작용할 때 SQL 쿼리를 문자열로 작성하는 대신 Java 코드로 쿼리를 작성할 수 있게 해준다.

QueryDLS의 장점

QueryDSL의 장점은 크게 4가지 이다.

  1. 문자가 아닌 코드로 쿼리를 작성할 수 있어 컴파일 시점에 문법 오류를 확인할 수 있다.
  2. 복잡한 쿼리나 동적 쿼리 작성이 편리하다.
  3. 쿼리 작성 시 제약 조건 등을 메서드 추출을 통해 재사용할 수 있다.
  4. JPQL 문법과 유사한 형태로 작성할 수 있어 쉽게 적응할 수 있다.

QueryDSL을 사용해야 할까?

QueryDSL을 무조건 사용해야 한다는 건 아니다.
다만 몇가지의 요소를 생각해보고 사용해야 할지 여부를 정해야한다.

복잡한 동적 쿼리의 필요성

만약 어플리케이션에서 복잡하고 동적인 쿼리를 자주 실행해야 한다면, QueryDSL을 사용하는 것이 좋다.
정적 SQL 쿼리만으로는 요구 사항을 충족하기 어려울 때 QueryDSL을 사용하여 동적 쿼리를 생성하고 실행할 수 있다.

타입 안정성 및 컴파일 타임 검사

QueryDSL은 타입 안정성을 제공하며, 컴파일 타임에 오류를 검출할 수 있도록 도와준다.

프로젝트의 복잡성과 요구 사항

프로젝트의 규모와 요구 사항에 따라 달라질 수 있다.
작은 프로젝트나 단순한 데이터베이스 상호 작용이라면 정적 SQL 쿼리만으로 충분할 수 있다.
그러나 대규모 프로젝트나 복잡한 데이터베이스 작업에서는 QueryDSL의 이점을 활용하기 좋다.

JPQL과 QueryDSL

JPQL

String username = "HongGilDong";
String jqpl = 'select m from Member m where m.username = :username";

List<Member> result = em.createQuery(jpql, Member.class)
					  .setParameter("username", username)
                      .getResultList();

QueryDSL

String username = "HongGilDong";

List<Member> result = queryFactory
        .selectFrom(member)
        .where(member.username.eq(username))
        .fetch();

JPQL과 QueryDSL의 차이점

  • 문법

    • JPQL은 문자열로 작성되며, 문법이 비교적 유연하다.
    • QueryDSL은 Java코드로 작성되며, 타입 안전성을 제공하며 IDE의 지원을 받을 수 있다.
  • 타입 안전성*

    • QueryDSL은 코드에서 엔티티 및 속성을 참조할 때 컴파일 타임에 타입 안전성을 제공한다.
    • JPQL은 문자열로 작성되어 컴파일 타임 오류가 발생하지 않고 런타임 시에 문제가 발견될 수 있다.
  • 가독성

    • QueryDSL은 Java 코드로 작성되므로 일반적으로 가독성이 더 높다.
    • JPQL은 문자열로 작성되기 때문에 복잡한 쿼리는 가독성이 낮을 수 있다.

QueryDSL 기본 문법

QueryFactory

  • 'queryFactory'는 QueryDSL을 시작하는 데 사용하는 핵심 객체이다.

Entity 클래스와 Q클래스

  • QueryDSL은 엔티티 클래스와 엔티티 클래스에 대한 Q클래스를 사용하여 쿼리 작성에 활용한다.
  • Q클래스는 컴파일 시점에 자동 생성되며 엔티티의 각 속성을 상수 필드로 나타내어 타입 안정성을 제공한다.

기본 문법

  • selectFrom()
    • 쿼리의 시작 지점을 나타내며, 데이터베이스 테이블에서 데이터를 조회하기 위해 사용된다.
  • select()
    • 조회할 열을 지정하는 데 사용된다.
    • 열을 지정하지 않으면 모든 열을 가져올 수 있다.
  • where()
    • 조건을 지정하는 데 사용된다.
    • 엔티티의 속성을 비교하거나 다양한 논리 연산자를 사용하여 복잡한 조건을 구성할 수 있다.
  • orderBy()
    • 결과를 정렬하기 위해 사용된다.
    • 오름차순(asc) 또는 내림차순(desc) 순서로 정렬할 수 있다.
  • groupBy()
    • 결과를 그룹화하기 위해 사용된다.
    • 집계 함수와 함께 사용하여 그룹 단위로 집계 작업을 수행할 수 있다.
  • fetch() 및 fetchOne()
    • fetch()
      • 쿼리의 결과를 리스트로 반환한다.
      • 여러 개의 결과를 조회할 때 사용한다.
    • fetchOne()
      • 단일 결과를 반환한다.
      • 결과가 없거나 여러 개인 경우 예외를 발생시킨다.
  • join()
    • 다른 엔티티와 조인 작업을 수행하기 위해 사용된다.
    • INNER JOIN, LEFT JOIN, RIGHT JOIN 등의 조인 유형을 지원한다.

Q클래스

  • Q클래스는 QureyDSL과 함께 사용되며, JPA 엔티티 클래스에 대한 타입 안전한 쿼리를 작성하기 위해 생성된다.

Q클래스의 특징

  • Entity 클래스에 대한 QueryDSL 코드 생성자를 사용하여 생성된다.
  • QueryDSL 코드 생성자는 Q 타입의 클래스를 생성하며, 이 클래스는 Entity 클래스와 동일한 필드를 가지고 있다.
  • QueryDSL을 사용하여 복잡한 쿼리를 작성하고 실행할 때 Q클래스를 활용한다.

Q클래스 예시

import com.querydsl.core.types.dsl.*;

public class QUser extends EntityPathBase<User> {
    private static final long serialVersionUID = 1L;
    
    public static final QUser user = new QUser("user");

    public final NumberPath<Long> id = createNumber("id", Long.class);
    public final StringPath username = createString("username");
    public final StringPath email = createString("email");
    
    public QUser(String variable) {
        super(User.class, forVariable(variable));
    }
}
  • Q 클래스를 사용하여 QueryDSL을 활용하면 안전하고 유지보수가 쉬운 쿼리를 작성 할 수 있다.

0개의 댓글