berryberrybin / board-project

0 stars 0 forks source link

[JPA] 정렬 리펙토링 #29

Open berryberrybin opened 1 year ago

berryberrybin commented 1 year ago

최신등록순/오래된순 정렬

public class EnquiryRepositoryImpl implements EnquiryRepositoryCustom {

private final JPAQueryFactory queryFactory;

public EnquiryRepositoryImpl(EntityManager em) {
    this.queryFactory = new JPAQueryFactory(em);
}

@Override
public Page<Enquiry> searchEnquiryByCondition(EnquirySearchCondition condition, Pageable pageable) {
    List<Enquiry> content = queryFactory
        .select(enquiry)
        .from(enquiry)
        .where(getPredicatesOfCondition(condition))
        .orderBy(enquirySort(condition.getSortByNewest())) // 정렬 코드
        .offset(pageable.getOffset())
        .limit(pageable.getPageSize())
        .fetch();

    JPAQuery<Long> countQuery = queryFactory.select(enquiry.count())
        .from(enquiry)
        .where(getPredicatesOfCondition(condition));
    return PageableExecutionUtils.getPage(content, pageable, countQuery::fetchOne);
}

private Predicate[] getPredicatesOfCondition(EnquirySearchCondition condition) {
    return new Predicate[] {
        createdAtBetween(condition.getSearchPeriodType(), condition.getSearchStartDate(),
            condition.getSearchEndDate()),
        keywordByLike(condition.getSearchKeyword()),
        answerStatusTypeEq(condition.getAnswerStatus())
    };
}

    // 정렬 코드 
private OrderSpecifier<?> enquirySort(Boolean sortByNewest) {
    if (sortByNewest == null || sortByNewest) {
        return enquiry.createdAt.desc();
    } else {
        return enquiry.createdAt.asc();
    }
}

private BooleanExpression createdAtBetween(SearchPeriodType searchPeriodType, LocalDate searchStartDate,
    LocalDate searchEndDate) {

    if (searchPeriodType == null) {
        if (searchEndDate == null || searchStartDate == null) {
            return null;
        }
        LocalDateTime searchStartDateTime = searchStartDate.atStartOfDay();
        LocalDateTime searchEndDateTime = LocalDateTime.of(searchEndDate, LocalTime.MAX).withNano(0);
        return enquiry.createdAt.between(searchStartDateTime, searchEndDateTime);
    }

    LocalDate endDate = LocalDate.now();
    LocalDate startDate;
    switch (searchPeriodType) {
        case ONE_WEEK:
            startDate = endDate.minusWeeks(1);
            break;
        case ONE_MONTH:
            startDate = endDate.minusMonths(1);
            break;
        case THREE_MONTH:
            startDate = endDate.minusMonths(3);
            break;
        case SIX_MONTH:
            startDate = endDate.minusMonths(6);
            break;
        case ONE_YEAR:
            startDate = endDate.minusYears(1);
            break;
        default:
            return null;
    }

    LocalDateTime searchStartDateTime = startDate.atStartOfDay();
    LocalDateTime searchEndDateTime = LocalDateTime.of(endDate, LocalTime.MAX).withNano(0);
    return enquiry.createdAt.between(searchStartDateTime, searchEndDateTime);
}

private BooleanExpression keywordByLike(String searchKeyword) {
    if (searchKeyword == null) {
        return null;
    }
    String keyword = convertLikeKeyword(searchKeyword);
    return enquiry.question.like(keyword).or(enquiry.author.nickname.like(keyword));
}

private String convertLikeKeyword(String searchKeyword) {
    return "%" + searchKeyword + "%";
}

private BooleanExpression answerStatusTypeEq(AnswerStatus answerStatus) {
    return answerStatus != null ? enquiry.answerStatus.eq(answerStatus) : null;
}

}


```java
@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class EnquirySearchCondition {

    private SearchPeriodType searchPeriodType;

    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private LocalDate searchStartDate;
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private LocalDate searchEndDate;

    private String searchKeyword;

    private AnswerStatus answerStatus;

    private Boolean sortByNewest;

}
berryberrybin commented 1 year ago

정렬 코드

public class QueryDslOrderByMaker {

    public static OrderSpecifier[] from(Class type, Sort sort) {
        return sort.stream()
                .map(order -> {
                    Order direction = order.isAscending() ? Order.ASC : Order.DESC;
                    String property = order.getProperty();
                    PathBuilder pathBuilder = new PathBuilder(type, type.getSimpleName().substring(0, 1).toLowerCase() + type.getSimpleName().substring(1));
                    return new OrderSpecifier(direction, pathBuilder.get(property));
                })
                .collect(Collectors.toList())
                .toArray(OrderSpecifier[]::new);
    }

}
public class EnquiryRepositoryImpl implements EnquiryRepositoryCustom {

    private final JPAQueryFactory queryFactory;

    public EnquiryRepositoryImpl(EntityManager em) {
        this.queryFactory = new JPAQueryFactory(em);
    }

@Override
    public Page<Enquiry> searchEnquiryByCondition(EnquirySearchCondition condition, Pageable pageable) {
        List<Enquiry> content = queryFactory
            .select(enquiry)
            .from(enquiry)
            .where(getPredicatesOfCondition(condition))
            .orderBy(QueryDslOrderByMaker.from(Enquiry.class, pageable.getSort())) // 코드 변경
            .offset(pageable.getOffset())
            .limit(pageable.getPageSize())
            .fetch();

        JPAQuery<Long> countQuery = queryFactory.select(enquiry.count())
            .from(enquiry)
            .where(getPredicatesOfCondition(condition));
        return PageableExecutionUtils.getPage(content, pageable, countQuery::fetchOne);
    }
}

Postman 테스트 방식

image

image