섭섭한 개발일지

QueryDSL LIKE 삽질 본문

프로그래밍/JPA

QueryDSL LIKE 삽질

Seop 2024. 3. 23. 04:04

프로젝트에서 검색조건이 까다로운게 있었다.

 

상품을 검색할 때 선택한 카테고리 + 검색어를 통해 카테고리에 해당하면서 검색어를 포함한 상품을 반환하는 Query를 생성해야한다.

아래는 작성한 코드에서 생각대로 작동되지 않는 코드였다.

List<Item> items = jpaQueryFactory
        .select(item)
        .from(item)
        .leftJoin(itemProduct).on(item.eq(itemProduct.item))
        .leftJoin(product).on(itemProduct.product.eq(product))
        .leftJoin(maker).on(product.maker.eq(maker))
        .leftJoin(category).on(item.category.eq(category))
        .where(categoryPredicate.and(item.name.like(keyword))
                .or(categoryPredicate.and(product.name.like(keyword)))
                .or(maker.name.contains(keyword)))
        .fetch();

JPAQuery<Long> total = jpaQueryFactory
        .select(item.count())
        .from(item)
        .leftJoin(itemProduct).on(item.eq(itemProduct.item))
        .leftJoin(product).on(itemProduct.product.eq(product))
        .leftJoin(maker).on(product.maker.eq(maker))
        .leftJoin(category).on(item.category.eq(category))
        .where(categoryPredicate.and(item.name.like(keyword))
                .or(categoryPredicate.and(product.name.like(keyword)))
                .or(maker.name.contains(keyword)));

정상적으로 조인을 시켰고 categoryPredicate 에는 카테고리 조건들이 포함되어 있다.

그리고 and를 통해 각 검색어 조건을 넣었고 포함되어야 하는 키워드를 like 메서드를 통해서 작성을 했는데..

 

잘 안되는 것이다..

QueryDSL JPA에서 뽑아주는 쿼리는 아래와 같았다.

select
            i1_0.id,
            i1_0.category_id,
            i1_0.created_at,
            i1_0.deleted_at,
            i1_0.info,
            i1_0.name,
            i1_0.price,
            i1_0.type,
            i1_0.updated_at,
            p1_0.name,
            m1_0.name
        from
            item i1_0
        left join
            item_product ip1_0
                on i1_0.id=ip1_0.item_id
        left join
            product p1_0
                on ip1_0.product_id=p1_0.id
        left join
            maker m1_0
                on p1_0.maker_id=m1_0.id
        left join
            category c1_0
                on i1_0.category_id=c1_0.id
        where
            (
                c1_0.last_name='탁주/막걸리'
                or c1_0.last_name='과실주/와인'
            )
            and i1_0.name like '%1000%' escape '!'
            or (
                c1_0.last_name='탁주/막걸리'
                or c1_0.last_name='과실주/와인'
            )
            and p1_0.name like '%1000%' escape '!'
            or m1_0.name like '%1000%' escape '!';

텍스트 값은 내가 넣은 것이였고 쿼리를 작동시켜보면 원하는 결과를 가져다 줬다.

 

이때부터 삽질이 시작되었다.

쿼리는 정상이라고 생각이 되는데 어째서 시스템에서는 값이 안나오는지…

 

답이 나온건 생각보다 간단했다.

like() 메서드의 문제였다….

 

내가 너무 DB로 생각을 해서 작성을 한게 문제였던 것이다.

like() 는 쿼리가 발생할 때 내가 파라미터 값으로 넣은 값을 그대로 쿼리에 넣는다

like(keyword) = LIKE keyword 인거고 내가 원하는 쿼리를 얻기 위해서 like() 메서드를 이용하려고 했다면 like(”%”+keyword+”%”)

 

이런 식으로 줘야했던 것이다.

 

 

다만 내가 만드려고 한 기능은 지원을 하는 contains()메서드를 사용하면 되서 like를 단순히 변경한 것으로 완만히 해결이 되었다…

List<Item> items = jpaQueryFactory
        .select(item)
        .from(item)
        .leftJoin(itemProduct).on(item.eq(itemProduct.item))
        .leftJoin(product).on(itemProduct.product.eq(product))
        .leftJoin(maker).on(product.maker.eq(maker))
        .leftJoin(category).on(item.category.eq(category))
        .where(categoryPredicate.and(item.name.contains(keyword))
                .or(categoryPredicate.and(product.name.contains(keyword)))
                .or(maker.name.contains(keyword)))
        .fetch();

JPAQuery<Long> total = jpaQueryFactory
        .select(item.count())
        .from(item)
        .leftJoin(itemProduct).on(item.eq(itemProduct.item))
        .leftJoin(product).on(itemProduct.product.eq(product))
        .leftJoin(maker).on(product.maker.eq(maker))
        .leftJoin(category).on(item.category.eq(category))
        .where(categoryPredicate.and(item.name.contains(keyword))
                .or(categoryPredicate.and(product.name.contains(keyword)))
                .or(maker.name.contains(keyword)));

 

Comments