Programming/Spring Boot

Querydsl 서브쿼리 사용하는 방법(select절, where절)

Jan92 2022. 8. 24. 21:03
반응형

Querydsl 서브쿼리

'Querydsl 서브 쿼리 사용법'에 대해 간단하게 정리한 내용입니다.

Querydsl이 나오게 된 배경을 살펴보고 이어서 subquery를 적용하는 코드 예시가 있는데요.

 

Querydsl의 경우 다른 것 보다 사용하기 위한 설정이 조금 번거로울 수 있는데, 환경설정 및 DTO 조회 방법, 페이징 처리 등의 추가적인 내용이 담긴 글 또한 해당 포스팅 맨 하단에 링크되어 있으니 필요시 참고해주시면 될 것 같습니다.

 

 


 

 

Querydsl이 나오게 된 배경

Spring Data JPA에서 기본적으로 제공해주는 CRUD 쿼리 메서드로 해결하지 못하는 복잡한 쿼리나 동적 쿼리를 처리하기 위해서 JPQL을 작성하게 되는데요.

 

/*

JPQP(Java Persistence Query Language)

JPQL은 테이블이 아닌 Entity 객체를 대상으로 검색하는 객체 지향 쿼리로 SQL과 비슷한 문법을 가지며, JPA는 JPQL을 SQL문으로 변환하여 데이터베이스를 조회하게 됩니다.
JPQL은 SQL을 추상화하였기 때문에 특정 데이터베이스의 SQL에 의존하지 않는다는 특징이 있습니다.

*/

 

String jpql = “select m from Member as m where m.name = ‘jan92’”;

위 예시는 간단한 JPQL인데 실제로 JPQL을 사용하게 된다면 복잡한 로직에 적용될 것이기 때문에 쿼리 문자열이 상당히 길어지게 되며, 때문에 오타 혹은 문법적 오류가 발생할 수 있고, 이는 런타임 에러로 이어질 수 있다는 문제점이 있습니다.

 

이런 JPQL의 불편함을 해소하기 위해 나온 것이 바로 'Querydsl'인데요.

Querydsl을 사용하게 되면 문자가 아닌 코드로 쿼리를 작성하기 때문에 컴파일 시점에서 문법 오류를 확인할 수 있다는 장점이 있으며, 동적인 쿼리의 작성이 편해집니다.

또한 쿼리에 적용되는 제약 조건 등을 메서드로 추출하여 재사용할 수 있다는 장점도 있습니다.(BooleanBuilder)

 

(동적인 쿼리의 작성이 편리해지지만 통계성 쿼리 등, 구현할 수 없는 쿼리는 존재합니다.)

 

Querydsl을 사용하기 위한 설정이 조금 번거로우며, 사용 방법 또한 따로 배워야 하지만 한번 사용하게 되면 계속 사용하게 되는 기능이라고 생각됩니다.

 

 


 

 

1. select SubQuery (Select 절의 서브 쿼리)

QBoard subBoard = new QBoard("subBoard");

public void selectSubQuery() {
    
    List<Tuple> result = queryFactory
                             .select(board.title,
                                     board.views,
                                     JPAExpressions.select(subBoard.views.avg())
                                             .from(subBoard)
                             )
                             .from(board)
                             .fetch();
}

같은 Entity를 사용했을 때, 메인 쿼리와 서브 쿼리의 별칭이 겹치면 안 되기 때문에 QBoard 객체를 하나 더 생성해줘야 하며, 이때 Alias를 직접 지정해줘야 합니다. (= subBoard)

 

서브 쿼리는 JPAExpressions를 통해 생성하게 되는데, select 절의 서브 쿼리에서 만약 결과에 대한 Alias를 지정하고 싶은 경우 아래와 같이 ExpressionUtils.as() 메서드를 통해 서브 쿼리를 한번 감싸주면서 Alias를 지정할 수 있습니다.

ExpressionUtils.as(
    JPAExpressions.select(subBoard.views.avg())
            .from(subBoard),
    "customAlias")        
)

 

 

 

2. where SubQuery (Where 절의 서브 쿼리)

QBoard subBoard = new QBoard("subBoard");

public void whereSubQuery() {
    
    List<Board> result = queryFactory
                            .selectFrom(board)
                            .where(board.views.geo(
                                JPAExpressions.select(subBoard.views.avg())
                                        .from(subBoard)
                            ))
                            .fetch();
}

where 절의 서브 쿼리 역시 JPAExpressions를 통해 생성하게 됩니다.

 

 

(Querydsl은 From 절에서의 SubQuery를 지원하지 않습니다.)

 

/*

끝으로 서브 쿼리의 경우 성능적인 측면에서 대부분 좋지 않기 때문에 다른 방법을 통해 처리할 수 있다면, 사용을 지양하는 것이 좋습니다.

(쿼리를 나눠서 실행하거나, join을 통해 해결)

*/

 

 

< Querydsl 연관 자료 >

 

Querydsl 개념 및 Gradle 환경설정 (gradle-7.x.x)

- Querydsl 개념 및 Gradle 환경설정 QUser user = QUser.user; List result = queryFactory .select(user) .from(user) .where(user.name.eq("Jan")) .fetch(); // SELECT * FROM user WHERE user.name = 'Jan'..

wildeveloperetrain.tistory.com

 

 

Querydsl DTO 조회하는 방법(Projection, @QueryProjection)

Projection 연산이란, - 한 Relation의 Attribute들의 부분 집합을 구성하는 연산자입니다. - 결과로 생성되는 Relation은 스키마에 명시된 Attribute들만 가집니다. - 결과 Relation은 기본 키가 아닌 Attribute..

wildeveloperetrain.tistory.com

 

 

Querydsl Paging 페이징 처리, Custom PageRequest 사용하는 이유

'Querydsl Paging 페이징 처리' 프로젝트에서 Get요청을 통해 여러 건의 데이터를 가져올 때, 페이징(Paging) 처리가 필요한 경우가 많습니다. Spring Boot에서는 Pageable, PageRequest를 사용하여 페이징 처리를

wildeveloperetrain.tistory.com

반응형