본문 바로가기
웹 개발/맨땅에 헤딩 프로젝트

Querydsl을 통한 동적 쿼리

by L3m0n S0ju 2022. 5. 23.

 

스프링을 공부하기 위해 시작했던 맨땅에 헤딩 프로젝트가 이번 글을 마지막으로 끝내고 react 프론트엔드 쪽도 조금 공부해서 다른 토이 프로젝트를 시작해볼까 생각 중이다.

 

현재 프로젝트는 기능은 이전에 모두 구현했고 코드도 Spring Boot Data를 통해 가능한 많이 코드를 줄였고 마지막으로 Querydsl 기술을 통해 동적 쿼리 코드 부분을 간단하고 가독성 있게 수정하였다.

 

 

 

 

 

 

 

 

 

 

 

 

 

수정 코드 깃허브 주소

https://github.com/Lemon-soju/Java_Sping_Shop_Project_01/commit/4c7c85092315b07ae183e1a1f7867ac2ed5fb8f8

 

Merge pull request #24 from Lemon-soju/slave-01 · Lemon-soju/Java_Sping_Shop_Project_01@4c7c850

Improve Dynamic Query By Querydsl

github.com

 

 

 

 

 

원래 코드는 다음과 같다. JPA만을 이용해서 동적 쿼리를 구성하면 아래와 같이 코드가 너무 길어서 한 눈에 들어오지 않고 매우 복잡해서 현재는 거의 쓰이지 않는다고 한다.

 

public List<Order> findAllByString(OrderSearch orderSearch) {
    //language=JPAQL
    String jpql = "select o From Order o join o.user m";
    boolean isFirstCondition = true;
    //주문 상태 검색
    if (orderSearch.getOrderStatus() != null) {
        if (isFirstCondition) {
            jpql += " where";
            isFirstCondition = false;
        } else {
            jpql += " and";
        }
        jpql += " o.status = :status";
    }
    //회원 이름 검색
    if (StringUtils.hasText(orderSearch.getUserName())) {
        if (isFirstCondition) {
            jpql += " where";
            isFirstCondition = false;
        } else {
            jpql += " and";
        }
        jpql += " m.name like :name";
    }
    TypedQuery<Order> query = em.createQuery(jpql, Order.class)
            .setMaxResults(1000); //최대 1000건
    if (orderSearch.getOrderStatus() != null) {
        query = query.setParameter("status", orderSearch.getOrderStatus());
    }
    if (StringUtils.hasText(orderSearch.getUserName())) {
        query = query.setParameter("name", orderSearch.getUserName());
    }
    return query.getResultList();
}

 

 

 

 

 

 

Querydsl을 이용해서 동적 쿼리를 아래 처럼 예쁘게 작성했다. 가독성이 매우 좋아 유지 보수에도 전혀 문제가 없다.

 

    public List<Order> findAllByString(OrderSearch orderSearch) {

        JPAQueryFactory queryFactory = new JPAQueryFactory(em);
        
        return queryFactory
                .selectFrom(order)
                .join(order.user, user)
                .where(
                        orderStatusEq(orderSearch.getOrderStatus()),
                        nameLike(orderSearch.getUserName()))
                .limit(1000)
                .fetch();
    }

    private BooleanExpression orderStatusEq(OrderStatus orderStatusCond){
        return orderStatusCond == null ? null : order.status.eq(orderStatusCond);
    }

    private BooleanExpression nameLike(String nameCond){
        return !StringUtils.hasText(nameCond) ? null : user.name.like(nameCond);
    }
}

댓글