개발꿀팁
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문법을 정리해보는 포스팅도 작성하면 좋을 것 같네요👍
'개발 하나둘셋 > Java & Spring' 카테고리의 다른 글
SpringBoot 슬랙 Slack알림보내기 ChatPostMessageRequest (0) | 2022.06.15 |
---|---|
SpringBoot SMTP서버를 활용한 메일 보내기 (0) | 2022.06.07 |
spring 게시판 기간조회 방법! String -> LocalDateTime 변환 (0) | 2022.04.25 |
스프링 DI ,IOC, AOP (0) | 2022.04.11 |
Spring에서 Redis Sorted set으로 인기검색어 순위 나타내기 (4) | 2022.01.15 |