Spring/Spring Boot

[Spring] querydsl orderby null - 동적 정렬 스킵하기

민돌v 2023. 2. 3. 20:56
728x90

 

 

queryDsl 에서 OrderSpecifier 를 사용하여 동적으로 정렬할 컬럼을 지정할 수 있습니다. (참고)

✨이번 게시글에서는, 동적 정렬 시 특정조건에서는 정렬을 하지않는 방법에 대해서 정리해보겠습니다.

 

 


👏🏻 사건의 발단은 이렇습니다.

  • where 절의 BooleanExpression 처럼, null 을 반환하면 조건에 무시될 것이라 생각해서
  • OrderSpecifier 에서 조건에 맞지않으면 null 을 반환하여 orderBy 를 무시하자라는 무식생각으로 접근을 해보았습니다.
public List<entity> getSortFiledEntityList(String field) {

    return queryFactory
        .select(..)
        .from(qEntity)
        .orderBy(sortByField(field))
        .fetch();
}

private OrderSpecifier<?> sortByField(final String fieldName) {

    Order order = Order.DESC;

    if (fieldName == "name") {
        return new OrderSpecifier<>(order, qEntity.name);
    }
    if (fieldName == "priority") {
        return new OrderSpecifier<>(order, qEntity.priority);
    }
    if (fieldName == "recordBirty") {
        return new OrderSpecifier<>(order, qEntity.recordBirty);
    }
    
    return null;
}

⬇️

 

👏🏻 QueryDsl 의 orderBy 는 null 을 지원하지 않음

  • 하지만 querDsl 의 orderBy는 orderBy(null) 을 지원하지 않아 다른 방법을 찾아야 했고 찾은 방법이  NullExpression.DEFAULT 을 사용하는 것 이었습니다.
  • querDsl 공식문서를 보면 Null 을 사용해야하는 경우 NullExpression.DEFAULT 사용을 권장하고 있습니다.
  • 따라서 아래처럼 OrderSpecifier 를 반환하면 쿼리상 orderby null asc 가 날라가게 됩니다.
return new OrderSpecifier(Order.ASC, NullExpression.DEFAULT, NullHandling.Default);

 

 

👏🏻 전체 코드

  • 향로님의 블로그를 보니, 아예 해당 OrderSpecifier(Null) 객체를 반환하는 유틸 클래스를 만들어서 사용하시기에
  • 이를 싱글톤 객체로 추출해서 사용해 주었습니다.

OrderByNull

public class OrderByNull extends OrderSpecifier {

    private static final OrderByNull DEFAULT = new OrderByNull();

    private OrderByNull() {
        super(Order.ASC, NullExpression.DEFAULT, NullHandling.Default);
    }

    public static OrderByNull getDefault() {
        return OrderByNull.DEFAULT;
    }
}

OrderSpecifier QueryDsl

private OrderSpecifier<?> sortByField(final String fieldName) {

    Order order = Order.DESC;

	//명시적으로 기록하기위해 isNull 사용
    if (Objects.isNull(fieldName)) {
        return OrderByNull.getDefault();
    }
    
    if (fieldName == "name") {
        return new OrderSpecifier<>(order, qEntity.name);
    }
    if (fieldName == "priority") {
        return new OrderSpecifier<>(order, qEntity.priority);
    }
    if (fieldName == "recordBirty") {
        return new OrderSpecifier<>(order, qEntity.recordBirty);
    }
    
	return OrderByNull.getDefault();
}

 

📌 개인적인 생각

group by 절을 최적화하기 위해 orderby null 을 사용하는게 아니라면 사실상 orderby idx 를 하는게 성능 이점도 있고 번거롭게 클래스를 새로 생성하지 않아서 좋다고 생각합니다.

다만, 저의 경우 정렬하는 메소드의 이름에서부터 알 수 있듯이  해당 메소드의 확실한 책임을 주고싶어 이렇게 작성을 하였습니다.

실제 조회하는 테이블의 컬럼의 수도 많지 않고 조건문도 많이 들어가는 상황이라 정렬하려는 컬럼과 동떨어진 index 정렬 코드 1줄을 넣고싶지않아 이렇게 작성을 하였습니다.

이 글을 보시는 분은 본인의 상황에 맞게 효율적인 선택을 하시길 바라겠습니다.

 

 

끝! 

 

 

 


반응형