QueryDSL을 이용한 이벤트 조회 기능 구현

song yuheon·2023년 10월 21일

Spring Project

목록 보기
6/7
post-thumbnail

이 글에서는 Spring Boot 환경에서 QueryDSL을 사용하여 특정 조건에 맞는 이벤트 목록을 조회하고 결과를 화면에 표시하는 방법에 대해 설명한다.
도서 기부 이벤트 정보를 조회하는 기능을 구현하고 페이징 처리와 날짜 범위 검색 기능을 추가하여 사용자가 원하는 데이터를 쉽게 찾을 수 있도록 설계하였다.

구현

1. 의존성 추가


build.gradle 파일에 QueryDSL과 Thymeleaf 관련 의존성을 추가한다.

2. 엔터티 및 레파지토리 구현

BookDonationEvent 엔터티 클래스와 이를 상속받는 JPA 레파지토리를 생성한다.

@Entity(name = "book_donation_event")
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Builder
public class BookDonationEvent {
    @Id @GeneratedValue
    @Column(name="donation_id")
    private Long donationId;

    @Column(name="created_at")
    private LocalDateTime createdAt;

    @Column(name="closed_at")
    private LocalDateTime closedAt;

    // 단 방향
    @Builder.Default
    @OneToMany(fetch = FetchType.LAZY,orphanRemoval = true)
    @JoinColumn(name="donation_id")
    private List<BookApplyDonation> bookApplyDonations=new ArrayList<>();

    /**
     * 양방향
     */
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "bookDonationEvent", cascade = CascadeType.REMOVE)
    private List<Book> books = new ArrayList<>();

    public BookDonationEvent(BookDonationEventRequestDto bookDonationEventRequestDto){
        this.createdAt = bookDonationEventRequestDto.getCreatedAt();
        this.closedAt = bookDonationEventRequestDto.getClosedAt();
    }

    public void update(BookDonationEventRequestDto bookDonationEventRequestDto) {
        this.createdAt = bookDonationEventRequestDto.getCreatedAt();
        this.closedAt = bookDonationEventRequestDto.getClosedAt();
    }

    public void addBook(Book book){
        this.books.add(book);
        book.addBookDonationEvent(this);
    }
    public void removeBook(Book book){
        this.books.remove(book);
        book.removeBookDonationEvent();
    }

}


@Repository
public interface BookDonationEventRepository extends JpaRepository<BookDonationEvent, Long>, QuerydslPredicateExecutor<BookDonationEvent> {
}

3. 서비스 구현

QueryDSL을 사용하여 도서 기부 이벤트 정보를 조회하는 서비스 메서드를 구현한다.

@Service
public class BookDonationEventService {
    
    @Autowired
    private BookDonationEventRepository bookDonationEventRepository;

    public BookDonationEventOnlyPageResponseDto getDonationEventOnlyV3(Pageable pageable, Long donationId, LocalDate eventStartDate, LocalDate eventEndDate) {
        QBookDonationEvent qBookDonationEvent = QBookDonationEvent.bookDonationEvent;
        BooleanBuilder builder = new BooleanBuilder();

        if(donationId != null)
            builder.and(qBookDonationEvent.donationId.eq(donationId));
        if(eventStartDate != null)
            builder.and(qBookDonationEvent.createdAt.after(eventStartDate.atStartOfDay()));
        if(eventEndDate != null)
            builder.and(qBookDonationEvent.closedAt.before(eventEndDate.atStartOfDay()));

        Page<BookDonationEvent> bookDonationEvents = bookDonationEventRepository.findAll(builder, pageable);
        int totalPages = bookDonationEvents.getTotalPages();
        List<BookDonationEventOnlyResponseDto> bookDonationEventResponseDtos = bookDonationEvents.stream()
                                                                                                .map(BookDonationEventOnlyResponseDto::new)
                                                                                                .toList();
        return new BookDonationEventOnlyPageResponseDto(bookDonationEventResponseDtos, totalPages);
    }
}

4. 컨트롤러 구현

HTTP 요청을 처리하는 컨트롤러 메서드를 구현한다.

@Controller
@RequestMapping("/users/bookDonationEvent")
public class BookDonationEventController {

    @Autowired
    private BookDonationEventService bookDonationEventService;

    @GetMapping("/v3")
    public String bookDonationEventOnlyV3(@RequestParam(defaultValue = "0") int page,
                                          @RequestParam(required = false) Long eventId,
                                          @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate eventStartDate,
                                          @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate eventEndDate,
                                          Model model) {
        PageRequest pageRequest = PageRequest.of(page, 8);

        BookDonationEventOnlyPageResponseDto bookDonationEventOnlyPageResponseDto =
                bookDonationEventService.getDonationEventOnlyV3(pageRequest, eventId, eventStartDate, eventEndDate);

        model.addAttribute("currentPage", page);
        model.addAttribute("totalPages", bookDonationEventOnlyPageResponseDto.getTotalpages());
        model.addAttribute("events", bookDonationEventOnlyPageResponseDto.getBookDonationEventOnlyResponseDtos());

        return "/users/bookDonationEventV3";
    }
}

5. Thymeleaf 템플릿 구현

화면에 데이터를 표시하기 위한 Thymeleaf 템플릿을 구현한다.

<!-- 검색 HTML 코드 그 외는 생략 한다.  -->
            <div class="container-container1">
                <form th:action="@{/users/bookDonationEvent/v3}" method="get" class="row">
                    <div class="col-3 mb-2">
                        <input type="text" class="form-control" id="eventId" name="eventId" placeholder="이벤트 ID">
                    </div>
                    <div class="col-3 mb-2">
                        <input type="date" class="form-control" id="eventStartDate" name="eventStartDate" placeholder="시작 날짜">
                    </div>
                    <div class="col-3 mb-2">
                        <input type="date" class="form-control" id="eventEndDate" name="eventEndDate" placeholder="종료 날짜">
                    </div>
                    <div class="col-3 mb-2">
                        <button type="submit" class="btn btn-primary w-100">검색</button>
                    </div>
                </form>

            </div>

결과 화면




profile
backend_Devloper

0개의 댓글