관리 메뉴

Mini

주문 검색 기능 개발 // 동적쿼리해결방법 본문

Java/Spring-app

주문 검색 기능 개발 // 동적쿼리해결방법

Mini_96 2023. 7. 4. 23:27

* 동적쿼리문제

- 주문상태가 Order인것만 보여줘야함 // select * from * where ...

- 주문상태가 기본이면 상관없이 다 보여줘야함 // select * from * where X

 

class OrderRepository

해결1 : String 노가다

public List<Order> findAllByString(OrderSearch orderSearch) {
    //language=JPAQL
        String jpql = "select o From Order o join o.member 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.getMemberName())) {
            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.getMemberName())) {
            query = query.setParameter("name", orderSearch.getMemberName());
        }
        return query.getResultList();
    }

단점 : 개발자실수가능성, 노가다성

 

해결2 : JPA표준 Criteria

/**
     * 문제 : 동적쿼리?
     * JPA Criteria로 해결하는법
     * 단점:무슨쿼리생성될지 파악어려움 => 유지보수 망
     */
    public List<Order> findAllByCriteria(OrderSearch orderSearch) {
        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<Order> cq = cb.createQuery(Order.class);
        Root<Order> o = cq.from(Order.class);
        Join<Order, Member> m = o.join("member", JoinType.INNER); //회원과 조인
        List<Predicate> criteria = new ArrayList<>();
        //주문 상태 검색
        if (orderSearch.getOrderStatus() != null) {
            Predicate status = cb.equal(o.get("status"),
                    orderSearch.getOrderStatus());
            criteria.add(status);
        }
        //회원 이름 검색
        if (StringUtils.hasText(orderSearch.getMemberName())) {
            Predicate name =
                    cb.like(m.<String>get("name"), "%" +
                            orderSearch.getMemberName() + "%");
            criteria.add(name);
        }

        cq.where(cb.and(criteria.toArray(new Predicate[criteria.size()])));
        TypedQuery<Order> query = em.createQuery(cq).setMaxResults(1000); //최대1000건
        return query.getResultList();
    }

단점 : 무슨 SQL이 만들어질지 파악어려움 => 유지보수 어려움

 

해결3: 쿼리dsl

지금작동은 안된다. 추후강의에서 배워보자

public List<Order> findAll(OrderSearch orderSearch){
        
        Order order=QOrder.order;
        QMember member=Qmember.member;
        
        return query
                .select(order)
                .from(order)
                .join(order.member, member)
                .where(statusEq(order.getOrderStatus()),
                        nameLike(orderSearch.getMemberName()))
                .limit(1000)
                .fetch();
    }
    
    private BooleanExpression statusEq(OrderStatus statusCond){
        if(statusCond==null){
            return null;
        }
        return order.status.eq(statusCond);
    }
    
    private BooleanExpression nameLike(String nameCond){
        if(!StringUtils.hasText(nameCond)){
            return null;
        }
        return member.name.like(nameCond);
    }