Spring/Spring boot icia 75일차

Spring boot 게시판 검색기능, 검색기능 페이징처리

swkn 2023. 6. 9. 11:20

1. BoardRepsitory

1. 제목 q 로 검색

쿼리문으로 작성하지 않아도 JPA로 메서드 이름을 정의하면 자동으로 쿼리문을 완성해 준다.

    // 제목으로 검색
    // select * from board_table where board_title like concat('%','q','%')
    // Containing = like

제목으로 q라는 값을 검색하면 쿼리문은

select * from board_table where board_title like concat('%','q','%')

으로 작성해 볼 수 있었다.

List<BoardEntity> findByBoardTitleContaining(String q);

Repository에서는 위와 같이 사용할 수 있다.

 

    @Test
    @DisplayName("검색 기능 테스트")
    public void searchTest() {
        List<BoardEntity> boardEntityList = boardRepository.findByBoardTitleContaining("2");
        boardEntityList.forEach(boardEntity -> {
            System.out.println(BoardDTO.toDTO(boardEntity));
        });

    }

테스트 코드로 테스트를 해보자면

q값에 2를 주고 테스트를 해보겠다.

boardTitle에 2가 들어간 값이 모두 조회되는 것을 볼 수 있었다.

findByBoardTitleContaining에 Containing은 SQL쿼리문의 "Like"와 같다고 볼 수 있다.

 

 

2. 작성자 q로 검색

 

 

마찬가지로 이번엔 제목이 아닌 작성자로 검색을 하고 싶다면

 

List<BoardEntity> findByBoardWriterContaining(String q);
    @Test
    @DisplayName("작성자 검색 기능 테스트")
    public void searchWriterTest() {
        List<BoardEntity> boardEntityList = boardRepository.findByBoardWriterContaining("2");
        boardEntityList.forEach(boardEntity -> {
            System.out.println(BoardDTO.toDTO(boardEntity));
        });
    }

테스트 코드는 이렇게 작성할 수 있을 것이다.

 

 

3. 작성자 q로 검색한 것을 id로 내림차순 정렬

List<BoardEntity> findByBoardWriterContainingOrderByIdDesc(String q);
    @Test
    @DisplayName("작성자 검색 기능 id 기준 내림차순 테스트")
    public void searchWriterOrderByIdDescTest() {
        List<BoardEntity> boardEntityList = boardRepository.findByBoardWriterContainingOrderByIdDesc("2");
        boardEntityList.forEach(boardEntity -> {
            System.out.println(BoardDTO.toDTO(boardEntity));
        });
    }

 

id 기준으로 내림차순 정렬까지 되는 것을 볼 수 있다.

 

4. 제목 또는 작성자에 q 가 들어간 값  id로 내림차순 조회

List<BoardEntity> findByBoardTitleContainingOrBoardWriterContainingOrderByIdDesc(String q1,String q2);

조건이 2개기 때문에 매개변수를 2개 주어야 한다.

 

    @Test
    @Transactional
    @DisplayName("제목 또는 작성자 검색 테스트")
    public void searchWriterOrsearchTitleTest() {
        String q = "20";
        List<BoardEntity> boardEntityList = boardRepository.findByBoardTitleContainingOrBoardWriterContainingOrderByIdDesc(q,q);
        boardEntityList.forEach(boardEntity -> {
            System.out.println(BoardDTO.toDTO(boardEntity));
        });
    }

매개변수를 2개준다고 각각 다른값을 주면 에러가 난다.

 

 

2. 검색결과 페이징 처리

Page<BoardEntity> findByBoardWriterContaining(String q, Pageable pageable);

리턴타입을 Page으로 바꿔주고 매개변수에 Pageable 변수를 담아준다.

 

    @Test
    @Transactional
    @DisplayName("검색 결과 페이징처리")
    public void searchPaging() {
        String q = "2";
        int page = 0;
        int pageLimit = 3;
        Page<BoardEntity> boardEntities = boardRepository.findByBoardWriterContaining(q, PageRequest.of(page, pageLimit, Sort.by(Sort.Direction.DESC, "id")));
        Page<BoardDTO> boardEntityPage = boardEntities.map(boardEntity ->
                BoardDTO.builder()
                        .id(boardEntity.getId())
                        .boardWriter(boardEntity.getBoardWriter())
                        .boardTitle(boardEntity.getBoardTitle())
                        .createdAt(UtilClass.dateFormat(boardEntity.getCreatedAt()))
                        .boardHits(boardEntity.getBoardHits())
                        .build()
        );
        System.out.println("boardEntities.getContent() = " + boardEntityPage.getContent()); // 요청페이지에 들어있는 데이터
        System.out.println("boardEntities.getTotalElements() = " + boardEntityPage.getTotalElements()); // 전체 글갯수
        System.out.println("boardEntities.getNumber() = " + boardEntityPage.getNumber()); // 요청페이지(jpa 기준)
        System.out.println("boardEntities.getTotalPages() = " + boardEntityPage.getTotalPages()); // 전체 페이지 갯수
        System.out.println("boardEntities.getSize() = " + boardEntityPage.getSize()); // 한페이지에 보여지는 글갯수
        System.out.println("boardEntities.hasPrevious() = " + boardEntityPage.hasPrevious()); // 이전페이지 존재 여부
        System.out.println("boardEntities.isFirst() = " + boardEntityPage.isFirst()); // 첫페이지인지 여부
        System.out.println("boardEntities.isLast() = " + boardEntityPage.isLast()); // 마지막페이지인지 여부
    }

테스트를 돌려보면

2로 검색된 갯수 = 15

페이지 번호 = 0

마지막 페이지 번호 = 5

한페이지에 보여지는 갯수 = 3

이전페이지 존재여부 = false

첫페이지 = true

마지막페이지 = false

 

 

즉 , 검색기능을 이용하려면 Repository에 쿼리문을 담은 메소드명을 제작후 , 페이징을 하고 싶다면 리턴과 매개변수를 Page로 바꾸어서 사용한다.

페이징처리하면서 Sort로 정렬기준을 보내기 때문에 OrderBy를 메소드에 적을 필요는 없다.