관리 메뉴

bright jazz music

[bootBoard] N:1(다대일) 연관관계: 11-7. 목록화면에서 검색 처리 본문

Framework/Spring

[bootBoard] N:1(다대일) 연관관계: 11-7. 목록화면에서 검색 처리

bright jazz music 2022. 10. 12. 21:45

https://github.com/hojuncha997/bootBoard

 

GitHub - hojuncha997/bootBoard: 코드로 배우는 스프링부트 웹 프로젝트 ch.5

코드로 배우는 스프링부트 웹 프로젝트 ch.5. Contribute to hojuncha997/bootBoard development by creating an account on GitHub.

github.com

 

1. list.html에 아래 코드 추가

 

검색을 위한 폼과 버튼을 추가한다. 이 폼은 테이블 위에 존재할 것이다.

<!-- 검색을 위한 추가 -->
<form action="/board/list" method="get" id="searchForm">
    <div class="input-group">
        <input type="hidden" name="page" value = "1">
        <div class="input-group-prepend">
            <select class="custom-select" name="type">
                <option th:selected="${pageRequestDTO.type == null}">-------</option>
                <option value="t" th:selected="${pageRequestDTO.type =='t'}" >제목</option>
                <option value="t" th:selected="${pageRequestDTO.type =='c'}"  >내용</option>
                <option value="t"  th:selected="${pageRequestDTO.type =='w'}" >작성자</option>
                <option value="tc"  th:selected="${pageRequestDTO.type =='tc'}" >제목 + 내용</option>
                <option value="tcw"  th:selected="${pageRequestDTO.type =='tcw'}" >제목 + 내용 + 작성자</option>
            </select>
        </div>
        <input class="form-control" name="keyword" th:value="${pageRequestDTO.keyword}">
        <div class="input-group-append" id="button-addon4">
            <button class="btn btn-outline-secondary btn-search" type="button">Search</button>
            <button class="btn btn-outline-secondary btn-clear" type="button">Clear</button>
        </div>
    </div>
</form>
<!-- 검색을 위한 추가 끝-->

 

이전 포스팅에서 게시했던 list.html은 내가 일부 코드를 빼먹어서 오류가 발생하였다. 따라서 수정하였다.

 

아래는 수정한 list.html 파일의 전문이며 구동에 문제가 없었다.

 

list.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">

<th:block th:replace="~{/layout/basic :: setContent(~{this::content} )}">

    <th:block th:fragment="content">

        <h1 class="mt-4">Board List Page
            <span>
                <a th:href="@{/board/register}">
                    <button type="button" class="btn btn-outline-primary">REGISTER
                    </button>
                </a>
            </span>
        </h1>

        <!-- 검색을 위한 추가 -->
        <form action="/board/list" method="get" id="searchForm">
            <div class="input-group">
                <input type="hidden" name="page" value = "1">
                <div class="input-group-prepend">
                    <select class="custom-select" name="type">
                        <option th:selected="${pageRequestDTO.type == null}">-------</option>
                        <option value="t" th:selected="${pageRequestDTO.type =='t'}" >제목</option>
                        <option value="t" th:selected="${pageRequestDTO.type =='c'}"  >내용</option>
                        <option value="t"  th:selected="${pageRequestDTO.type =='w'}" >작성자</option>
                        <option value="tc"  th:selected="${pageRequestDTO.type =='tc'}" >제목 + 내용</option>
                        <option value="tcw"  th:selected="${pageRequestDTO.type =='tcw'}" >제목 + 내용 + 작성자</option>
                    </select>
                </div>
                <input class="form-control" name="keyword" th:value="${pageRequestDTO.keyword}">
                <div class="input-group-append" id="button-addon4">
                    <button class="btn btn-outline-secondary btn-search" type="button">Search</button>
                    <button class="btn btn-outline-secondary btn-clear" type="button">Clear</button>
                </div>
            </div>
        </form>
        <!-- 검색을 위한 추가 끝-->


        <table class="table table-striped">
            <thead>
            <tr>
                <th scope="col">#</th>
                <th scope="col">Title</th>
                <th scope="col">Writer</th>
                <th scope="col">Regdate</th>
            </tr>
            </thead>
            <tbody>

            <tr th:each="dto : ${result.dtoList}">
                <th scope="row">
                    <a th:href="@{/board/read(bno = ${dto.bno},
                    page= ${result.page},
                    type=${pageRequestDTO.type} ,
                    keyword = ${pageRequestDTO.keyword})}">
                        [[${dto.bno}]]
                    </a>
                </th>
                <td>[[${dto.title}]] ---------------- [<b th:text="${dto.replyCount}"></b>]</td>
                <td>[[${dto.writerName}]] <small>[[${dto.writerEmail}]]</small></td>
                <td>[[${#temporals.format(dto.regDate, 'yyyy/MM/dd')}]]</td>
            </tr>

            </tbody>
        </table>

<!--        페이징-->
        <ul class="pagination h-100 justify-content-center align-items-center">

            <li class="page-item " th:if="${result.prev}">
                <a class="page-link" th:href="@{/board/list(page= ${result.start -1},
                    type=${pageRequestDTO.type} ,
                    keyword = ${pageRequestDTO.keyword} ) }" tabindex="-1">Previous</a>
            </li>

            <li th:class=" 'page-item ' + ${result.page == page?'active':''} " th:each="page: ${result.pageList}">
                <a class="page-link" th:href="@{/board/list(page = ${page} ,
                   type=${pageRequestDTO.type} ,
                   keyword = ${pageRequestDTO.keyword}  )}">
                    [[${page}]]
                </a>
            </li>

            <li class="page-item" th:if="${result.next}">
                <a class="page-link" th:href="@{/board/list(page= ${result.end + 1} ,
                    type=${pageRequestDTO.type} ,
                    keyword = ${pageRequestDTO.keyword} )}">Next</a>
            </li>

        </ul>
<!---->

        <div class="modal" tabindex="-1" role="dialog">
            <div class="modal-dialog" role="document">
                <div class="modal-content">
                    <div class="modal-header">
                        <h5 class="modal-title">Modal title</h5>
                        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                            <span aria-hidden="true">&times;</span>
                        </button>
                    </div>
                    <div class="modal-body">
                        <p>Modal body text goes here.</p>
                    </div>
                    <div class="modal-footer">
                        <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
                        <button type="button" class="btn btn-primary">Save changes</button>
                    </div>
                </div>
            </div>
        </div>

        <script th:inline="javascript">

            var msg = [[${msg}]];

            console.log(msg);

            if(msg){
                $(".modal").modal();
            }
            var searchForm = $("#searchForm");

            $('.btn-search').click(function(e){

                searchForm.submit();

            });

            $('.btn-clear').click(function(e){

                searchForm.empty().submit();

            });


        </script>



    </th:block>

</th:block>

 

검색 가능한 바가 추가되었음

 

 

 

2. BoardServiceImpl 클래스 코드 수정

getList() 일부 수정

//BoardServiceImpl.java


@Service
@RequiredArgsConstructor
@Log4j2
public class BoardServiceImpl implements BoardService {

    private final BoardRepository repository; // 자동 주입 final
    private final ReplyRepository replyRepository; //새롭게 추가

///...

	//목록처리
    @Override
    public PageResultDTO<BoardDTO, Object[]> getList(PageRequestDTO pageRequestDTO) {
        log.info(pageRequestDTO);

        Function<Object[], BoardDTO> fn =
                (en -> entityToDTO((Board)en[0], (Member)en[1], (Long)en[2]));
                                    //Board board, Member member, Long replyCount

     // Page<Object[]> result = repository.getBoardWithReplyCount(
     //           pageRequestDTO.getPageable(Sort.by("bno").descending()));
        
        Page<Object[]> result = repository.searchPage(
                pageRequestDTO.getType()
                , pageRequestDTO.getKeyword()
                , pageRequestDTO.getPageable(Sort.by("bno").descending())
        );

        return new PageResultDTO<>(result, fn);
    }

///...  



}

 

 

3. 프로젝트 구동

localhost:8080/board/list 접근

 

최근 페이지
가장 뒷 페이지

 

4. 검색 테스트

 

'제목 + 내용 + 작성자' 를 포함해서 1을 검색

 

 

콘솔 로그

 

2022-10-12 22:39:19.728  INFO 1696 --- [nio-8080-exec-4] c.e.b.controller.BoardController         : list.............PageRequestDTO(page=1, size=10, type=tcw, keyword=1)
2022-10-12 22:39:19.728  INFO 1696 --- [nio-8080-exec-4] c.e.bootboard.service.BoardServiceImpl   : PageRequestDTO(page=1, size=10, type=tcw, keyword=1)
2022-10-12 22:39:19.728  INFO 1696 --- [nio-8080-exec-4] c.e.b.r.s.SearchBoardRepositoryImpl      : searchPage............................
Hibernate: 
    select
        board0_.bno as col_0_0_,
        member1_.email as col_1_0_,
        count(reply2_.rno) as col_2_0_,
        board0_.bno as bno1_0_0_,
        member1_.email as email1_1_1_,
        board0_.moddate as moddate2_0_0_,
        board0_.reg_date as reg_date3_0_0_,
        board0_.content as content4_0_0_,
        board0_.title as title5_0_0_,
        board0_.writer_email as writer_e6_0_0_,
        member1_.moddate as moddate2_1_1_,
        member1_.reg_date as reg_date3_1_1_,
        member1_.name as name4_1_1_,
        member1_.password as password5_1_1_ 
    from
        board board0_ 
    left outer join
        member member1_ 
            on (
                board0_.writer_email=member1_.email
            ) 
    left outer join
        reply reply2_ 
            on (
                reply2_.board_bno=board0_.bno
            ) 
    where
        board0_.bno>? 
        and (
            board0_.title like ? escape '!' 
            or board0_.content like ? escape '!' 
            or member1_.email like ? escape '!'
        ) 
    group by
        board0_.bno 
    order by
        board0_.bno desc limit ?
2022-10-12 22:39:19.731  INFO 1696 --- [nio-8080-exec-4] c.e.b.r.s.SearchBoardRepositoryImpl      : [[Board(bno=102, title=Title...100, content=Content...100), Member(email=user100@aaa.com, password=11111, name=USER100), 0], [Board(bno=93, title=Title...91, content=Content...91), Member(email=user91@aaa.com, password=11111, name=USER91), 0], [Board(bno=83, title=Title...81, content=Content...81), Member(email=user81@aaa.com, password=11111, name=USER81), 1], [Board(bno=73, title=Title...71, content=Content...71), Member(email=user71@aaa.com, password=11111, name=USER71), 2], [Board(bno=63, title=Title...61, content=Content...61), Member(email=user61@aaa.com, password=11111, name=USER61), 0], [Board(bno=53, title=Title...51, content=Content...51), Member(email=user51@aaa.com, password=11111, name=USER51), 0], [Board(bno=43, title=Title...41, content=Content...41), Member(email=user41@aaa.com, password=11111, name=USER41), 0], [Board(bno=33, title=Title...31, content=Content...31), Member(email=user31@aaa.com, password=11111, name=USER31), 1], [Board(bno=23, title=Title...21, content=Content...21), Member(email=user21@aaa.com, password=11111, name=USER21), 1], [Board(bno=21, title=Title...19, content=Content...19), Member(email=user19@aaa.com, password=11111, name=USER19), 0]]
Hibernate: 
    select
        count(distinct board0_.bno) as col_0_0_ 
    from
        board board0_ 
    left outer join
        member member1_ 
            on (
                board0_.writer_email=member1_.email
            ) 
    left outer join
        reply reply2_ 
            on (
                reply2_.board_bno=board0_.bno
            ) 
    where
        board0_.bno>? 
        and (
            board0_.title like ? escape '!' 
            or board0_.content like ? escape '!' 
            or member1_.email like ? escape '!'
        )
2022-10-12 22:39:19.732  INFO 1696 --- [nio-8080-exec-4] c.e.b.r.s.SearchBoardRepositoryImpl      : COUNT: 20

where 절이 처리되는 방식을 주목할 것

 

 

 

 

Comments