개발 하나둘셋/Java & Spring

spring 게시판 기간조회 동적으로 처리하기 querydsl

유리코딩 2022. 5. 18. 14:48
반응형

개발꿀팁

spring 기간 조회 동적으로 처리하기

 

 

프로젝트 중 기간조회 기능이 필요해 작성하는 포스팅을 작성했었는데 코드를 더 동적으로 작성하자는 리뷰를 받고 수정해보았습니다

 

기존 코드

 

spring 게시판 기간조회 방법! String -> LocalDateTime 변환

개발꿀팁 spring 게시판 기간조회 방법! String -> LocalDateTime 변환 프로젝트 중 게시글을 임의의 기간으로 조회하는 기능이 필요해서 작성해봤습니다! 기간을 직접입력해서 조회할 때, String으로 받

yuricoding.tistory.com

 

 

게시글 기간 조회

예시 이미지

 

Controller

날짜 조회를 위한 시작 날짜와 끝날짜 설정을 위해 requestParam으로 시작날짜와 마지막 날짜를 받습니다.

날짜를 입력하지 않을 때는 자동으로 입력될 수 있도록 defaultValue 값을 줍니다.

@DateTimeFormat으로 입력받을 형식을 지정해줍니다.

날짜만 받기 때문에 형식은 LocalDate입니다.

저는 페이징을 위해 Pageable도 넣었습니다

@RestController
@RequiredArgsConstructor
@RequestMapping("/api")
public class PostController {

    private final PostService postService;
    
    @GetMapping("/post")
    public PageImpl<PostResponseDto> getPostList(@RequestParam(value = "searchStartDate", required = false, defaultValue = "19000101") @DateTimeFormat(pattern = "yyyyMMdd") LocalDate searchStartDate,
                                                 @RequestParam(value = "searchEndDate", required = false, defaultValue = "99991231") @DateTimeFormat(pattern = "yyyyMMdd") LocalDate searchEndDate,
                                                 @PageableDefault Pageable pageable
    ) {
        return postService.getPostList(searchStartDate, searchEndDate, pageable));
    }
}

 

Service

저는 보다 동적으로 처리하기 위해 Querydsl을 사용하였습니다

@Service
@Transactional
@AllArgsConstructor
public class PostService {

    private final PostRepositorySupport postRepositorySupport;

    public PageImpl<PostResponseDto> getPostList(String searchStartDate, String searchEndDate, Pageable pageable) {

        return postQueryRepository.filter(startDateTime, endDateTime, pageable);
    }
}

 

Repository

searchDateFilter라는 메서드를 별로도 만들어 조건문에 넣어줬습니다

여기서 특이점은 searchDateFilter메서드 안에 Querydsl 문법(goe, loe)입니다

 

post.createdAt.goe(LocalDateTime.of(searchStartDate, LocalTime.MIN))에서 goe는 .goe의 앞의 값이. goe 뒤 괄호 안의 값보다 크거나 같다는 것을 뜻합니다. (loe는 반대, 예시는 코드 아래 기록하였습니다)

 

또한 createdAt의 타입은 LocalDateTime으로 controller에서는 파라미터로 LocalDate만 받았기 때문에 LocalDateTime.of로 날짜와 시간을 입력해줍니다. 여기서 시간은 LocalTime.MIN으로 해서 최소시간(00:00)으로 해줍니다

 

LocalDateTime.of(searchEndDate, LocalTime.MAX).withNano(0)에서 .withNano(0)를 붙이는 이유는 LocalTime.MAX의 값이 '23:59:59.999999999'이기 때문에 그대로 사용하면 올림이 되어 '00:00'이 되어 버린다.... 뒤에 .withNano(0)를 붙여줌으로써 밀리세컨드 단위가 지워집니다

@Repository
public class PostQueryRepository extends QuerydslRepositorySupport {

    private final JPAQueryFactory queryFactory;

    public PostQueryRepository(JPAQueryFactory factory) {
        super(Post.class);
        this.queryFactory = factory;
    }

    public PageImpl<PostResponseDto> filter(LocalDateTime searchStartDate, LocalDateTime searchEndDate, Pageable pageable) {
        JPQLQuery<PostResponseDto> result = queryFactory
                .select(Projections.fields(PostResponseDto.class,
                        post.id, post.title, post.cont, post.created_at))
                .from(post)
                // 조건문
                .where(searchDateFilter(searchStartDate, searchEndDate))
                .orderBy(post.id.desc());
                
        long totalCnt = result.fetchCount();
        List<PostResponseDto> list = getQuerydsl().applyPagination(pageable, result).fetch();
        return new PageImpl<PostResponseDto.ListDto>(list, pageable, totalCnt);
    }
    
    // 날짜 필터
    private BooleanExpression searchDateFilter(LocalDate searchStartDate, LocalDate searchEndDate) {

	//goe, loe 사용
        BooleanExpression isGoeStartDate = post.createdAt.goe(LocalDateTime.of(searchStartDate, LocalTime.MIN));
        BooleanExpression isLoeEndDate = post.createdAt.loe(LocalDateTime.of(searchEndDate, LocalTime.MAX).withNano(0));

        return Expressions.allOf(isGoeStartDate, isLoeEndDate);
    }
}
Querydsl 문법
<범위 체크 사용 예시>
- x.goe(y); (x >= y)
- x.gt(y); (x > y)
- x.loe(y); (x <= y)
- x.lt(y); (x < y)

 

 

확실히 먼저 기록했던 코드보다 깔끔해지기도 했고, 동적 쿼리를 활용해 더욱 효율적인 코드가 완성된 듯하네요! 만족 만족 대만족! 

저 혼자였으면 앞선 코드에 만족했을 텐데 선임 개발자분이 조금 더 동적으로 작성해보라는 리뷰가 있어 더 찾아보고 작성했는데 모르고 넘어갔을 querydsl문법도 알게 된 좋은 기회였습니다!

다음에는 querydsl문법을 정리해보는 포스팅도 작성하면 좋을 것 같네요👍

 

반응형