Kotlin QueryDsl dynamic search

정명진·2023년 6월 10일
0
post-custom-banner

이번 사이드 프로젝트를 하며 다이나믹 옵션에 따라 검색이 가능한 화면을 만들어야 했다.

기본 JPA 에서 제공하는 정렬이나, 필터링 기능으로는 보기에 좋지 않아 방법이 없을까 하다가 QueryDsl로 해결을 했다.

@GetMapping("/view")
    fun view(authentication: Authentication, @RequestParam(name = "tag", required = false, defaultValue = "") tag: String, @RequestParam(name = "sort", required = false, defaultValue = "") sort: List<String>): ResponseEntity<ResponseDto>{
        val hashTagMainView = hashTagViewUseCase.getHashTagMainView(authentication.toUserId(), tag, sort)
        return ResponseEntity<ResponseDto>(DataResponseDto(hashTagMainView), HttpStatus.OK)
    }

검색 조건이 없으면 전체 결과를 보내줘야 했다. QueryDsl의 BooleanExpression을 활용하면 검색 조건이 만족하는게 없을 때 null을 주면 전체 검색을 하는 점과 다이나믹 정렬 조건을 쉽게 추가 할 수 있어서 바로 적용을 해봤다.

fun tagEq(tag: String): BooleanExpression? {
        return if (StringUtils.hasText(tag))  userHashTagJpaEntity.hashTag.text.eq(tag) else null
    }

    fun getSort(sort: List<String>): Array<OrderSpecifier<*>>{
        val sortSpecifications = mutableListOf<OrderSpecifier<*>>()

        for (value in sort) {
            if (value == "createdDate") {
                sortSpecifications.add(OrderSpecifier(Order.ASC, userHashTagJpaEntity.hashTag.createdDate))
            }else if (value == "-createdDate") {
                sortSpecifications.add(OrderSpecifier(Order.DESC, userHashTagJpaEntity.hashTag.createdDate))
            }
        }

        if (sortSpecifications.isEmpty()) {
            // 기본 옵션은 생성일 기준 오름차순
            sortSpecifications.add(OrderSpecifier(Order.ASC, userHashTagJpaEntity.hashTag.createdDate))
        }

        return sortSpecifications.toTypedArray()
    }

여기서 Array로 return한 이유는 QueryDsl의 orderBy 에 파라미터가 varargs로 전달해야 하기때문이다. 실제로 해당 옵션에 가보면

    /**
     * Add order expressions
     *
     * @param o order
     * @return the current object
     */
    Q orderBy(OrderSpecifier<?>... o);

위와 같이 설명되어있다. kotlin에서는 Array에 *을 붙여주면 varargs와 같이 넘겨줄 수 있기 때문에 List 대신 사용하게 되었다.

profile
개발자로 입사했지만 정체성을 잃어가는중... 다시 준비 시작이다..
post-custom-banner

0개의 댓글