Spring 기초 정리 - QueryDSL

Zyoon·2025년 6월 18일

Spring 기초정리

목록 보기
16/18
post-thumbnail

📘QueryDSL 초기 설정 및 사용법


QueryDSL 이란

  • QueryDSL은 Java 코드로 작성하는 JPQL/SQL 쿼리 빌더

QueyDSL 사용 이유?

  1. 컴파일 과정에서 에러 체크
    • JPQL사용 시 query 문을 String 으로 관리하기때문에, 해당 구문에 문제가 있어도 컴파일 과정에서 문제를 파악하기 힘들다
      //쿼리문에 문제가 있어도 컴파일은 실행된다.
      String query = "SELECT u FROM User u WHERE u.username = :username";
    • 하지만 QueryDSL 은 Java 코드로 작성되기 때문에 컴파일 과정에서 문제를 파악하기 쉽다.
      QUser user = QUser.user; //QueryDSL 에서 자동 생성하는 클래스
      
      User result = queryFactory
          .selectFrom(user)
          .where(user.username.eq(dto.getUsername())) //eq : Equal
          .fetchOne();
  1. 동적 쿼리 생성시 쉽고 깔끔하게 구현
    • 검색조건이 많은 경우 해당 조건이 있을수도 없을 수도 있다.
    • 그런 경우 쿼리문을 동적으로 처리해야 하는데, JPQL/JPA 에 비해 동적 쿼리 조건문이 간결하고 가독성 높다.
      BooleanBuilder where = new BooleanBuilder();
      // 날짜에 대한 동적 쿼리
      LocalDateTime start = dto.getStartDate();
      LocalDateTime end   = dto.getEndDate();
      
      if (start != null && end != null) {
          where.and(log.createdAt.between(start, end)); // 시작, 종료 모두 있을 경우
      } else if (start != null) {
          where.and(log.createdAt.goe(start));// 시작일만 있을 경우 (시작일 ~ 끝)
      } else if (end != null) {
          where.and(log.createdAt.loe(end));  // 종료일만 있을 경우 (처음 ~ 종료일)
      }
      
      List<Log> findList = queryFactory
                      .selectFrom(log)
                      .where(where)
      • BooleanBuilder 생성 후 조건에 따라 추가해준다.
      • 그 후, 쿼리문 생성시 where 조건에 추가해준다.

초기 세팅

  • Gradle 의존성 추가
    // Querydsl 추가 (Spring boot 3.x 이상)
    implementation 'com.querydsl:querydsl-jpa:5.1.0:jakarta'
    annotationProcessor "com.querydsl:querydsl-apt:5.1.0:jakarta" //Q클래스
    annotationProcessor "jakarta.annotation:jakarta.annotation-api"//어노테이션
    annotationProcessor "jakarta.persistence:jakarta.persistence-api"//어노테이션
  • Q클래스 생성 구문 터미널에서 입력
    ./gradlew clean build
  • Q클래스 생성 확인

Q클래스

  • QueryDSL 을 사용하면 기본적으로 QClass 라는 자식 클래스가 생성된다.
  • @Entity 클래스를 기준으로 생성되는 쿼리 전용 클래스

QClass 의 구조는 Entity 와 다를 것이 없는데, 따로 생성하는 이유는?

  • Q클래스는 SQL을 Java 문법으로 작성하기 위한 도구로 필드에 직접 접근 가능
  • 즉 Entity 가 테이블과 1:1 로 매핑되는 데이터라면, Q클래스는 Entity 를 검색할 수 있게 만든 도구
  • 그래서 쿼리를 안전하고 자동적으로 생성이 가능하게 만들어준다.

클래스 구조

  • QueryDSL을 쓸 때 흔히 JPA 인터페이스 + QueryDSL 인터페이스 + QueryDSL 구현 클래스 구조로 사용한다.
  • Spring Data JPA는 기본적으로 인터페이스 위주이지만, QueryDSL은 직접 구현해야 쿼리를 만들 수 있기 때문에 이 두 개를 자연스럽게 합치는 방식

1. JPA Repository (Spring에서 관리)

public interface LogRepository extends JpaRepository<Log, Long>, LogSearchRepository {
}
  • LogSearchRepository 쿼리 추가용 인터페이스

2. QueryDSL 인터페이스 (기능 명세서)

public interface LogSearchRepository {
    Page<Log> findAllFromQueryDsl(LogRequestDto logRequestDto, Pageable pageable);
}
  • 직접 구현할 메서드 선언

3. QueryDSL 구현 클래스

@Repository
@RequiredArgsConstructor
public class LogRepositoryImpl implements LogSearchRepository{

    private final JPAQueryFactory queryFactory;

    @Override
    public Page<Log> findAllFromQueryDsl(LogRequestDto dto, Pageable pageable) {
    // 쿼리 작성
    }
  • QueryDSL 쿼리 직접 작성

동적쿼리 기본 구조

@RequiredArgsConstructor
public class UserRepositoryImpl implements UserRepositoryCustom {

    private final JPAQueryFactory queryFactory;

    @Override
    public List<User> search(String name, UserRoleEnum role) {
        QUser user = QUser.user;

        return queryFactory
                .selectFrom(user)
                .where(
                    name != null ? user.name.eq(name) : null,
                    role != null ? user.role.eq(role) : null
                )
                .fetch();
    }
}
  • Q클래스 생성
  • name이나 rolenull이면 자동으로 제외

Where 조건

조건식의미
eq()같다
ne()같지 않다
gt()초과 (>)
lt()미만 (<)
goe()이상 (>=)
loe()이하 (<=)
contains()포함 (LIKE %값%)
startsWith()시작하는 문자열
endsWith()끝나는 문자열

  • 복합 조건일 경우 AND 나 OR 사용
//기본적으로 where() 안의 조건은 AND
.where(user.name.eq("karina"), user.role.eq(UserRoleEnum.USER))

//OR 조건 사용
.where(user.name.eq("karina").or(user.name.eq("winter")))
profile
기어 올라가는 백엔드 개발

0개의 댓글