[Spring] Spring Boot Data JPA + QueryDsl 페이징 적용하기

eugene.yi·2023년 1월 12일
0
post-thumbnail
post-custom-banner
  1. JPAQueryFactory를 Bean으로 등록해 어디서든 주입받아 사용할 수 있게 한다.
@Configuration
public class QuerydslConfig{
	
    @PersistenceContext
    private EntityManager entityManager;
    
    @Bean
    public JPAQueryFactory jpaQueryFactory(){
    	return new JPAQueryFactory(entityManager);
    }
}
  1. Repository를 생성한다.
@RequiredArgsConstructor
@Repository
public class NoticeQueryRepository {
	private final JPAQueryFactory queryFactory;
     
     public Page<Notice> findByConditions(NoticeSearchConditionsDto conditions, Pageable pageable){ 
     // 조건들이 담겨있는 객체인 NoticeSearchConditionsDto 와  Pageable 객체를 같이 넘겨준다.
        List<Notice> notices = queryFactory
                        .selectFrom(notice)
                        .where(
                                containsText(conditions.getSearchKind(), conditions.getSearchText()),
                                checkViewFlags(conditions.getViewFlag()),
                                notice.startDt.between(conditions.getStartDate(), conditions.getEndDate()),
                                notice.delFlag.eq("N")
                        )
                        .offset(pageable.getOffset()) //pageable 객체에서 꺼냄
                        .limit(pageable.getPageSize()) //pageable 객체에서 꺼냄
                        .orderBy(notice.id.desc())
                        .fetch();

        JPQLQuery<Notice> count = queryFactory
                        .selectFrom(notice)
                        .where(
                                containsText(conditions.getSearchKind(), conditions.getSearchText()),
                                checkViewFlags(conditions.getViewFlag()),
                                notice.startDt.between(conditions.getStartDate(), conditions.getEndDate()),
                                notice.delFlag.eq("N")
                        );
		
        /*리스트에 담겨있는 결과를 Page객체로 만들어준다. 
        count 쿼리를 따로 호출한다.*/
        return PageableExecutionUtils.getPage(notices, pageable,()->count.fetchCount());
    }

	// 조건문이 복잡한 경우 함수를 만들어 관리하면 좋다.
    private BooleanExpression containsText(String searchKind, String searchText ){
        if (searchKind.equals("title")){
            return notice.title.contains(searchText);
        }
        else if(searchKind.equals("contents")){
            return notice.contents.contains(searchText);
        }
        else{
            return null;
        }
    }

    private BooleanExpression checkViewFlags(String viewFlag) {
        if (viewFlag.equals("Y")){
            return notice.viewFlag.eq("Y");
        }
        else if (viewFlag.equals("N")){
            return notice.viewFlag.eq("N");
        } else{
            return null;
        }
    }
}
  1. View까지 Entity를 넘기지 않아야 하기 때문에, Service 단에서 Page객체를 받아
    Notice -> NoticeDto로 매핑해준다.
public Page<NoticeResponseDto> getNoticeList(NoticeSearchConditions searchConditions, 
											 Pageable pageable){
	return noticeQueryRepository.findByConditions(searchConditions, pageable)
    		.map(NoticeResponseDto::new);
}
  1. Controller 에서 호출할 때 Pageable객체를 같이 넘겨줌.
@PostMapping
public String showNoticeList(@RequestParam(required = false, defaultValue = "0", value = "page") int page,
                             @PageableDefault(size=10) Pageable pageable,
                             @ModelAttribute("searchConditions") NoticeSearchConditionsDto searchConditions,
                             Model model){
	
    Page<NoticeResponseDto> noticeList = noticeService.getNoticeList(searchConditions, pageable);
    
    model.addAttribute("searchConditions", searchConditions);
    ...
    return "customer/noticeList";
}

위 내용은 학습용으로 작성되어 틀린 부분이 있을 수 있습니다.
참고 : https://jojoldu.tistory.com/372

post-custom-banner

0개의 댓글