Spring - 게시글 검색

맑은 눈의 코드 👀·2023년 8월 31일
0

06_framework 이론

목록 보기
22/23
post-custom-banner

게시글 목록 조회에서 검색어 입력시 관련 게시글이 검색되도록 해보자

이전에 구현한 게시글 목록 조회에 참고해서 추가 기능을 넣어 볼 예정이다 .

🫧 boardList.jsp

 		<%-- 검색을 진행한 경우 파라미터 (key,query)를
            쿼리스트링 태로 저장한 변수  --%>
        <c:if test="${!empty param.key}" >
            <c:set var="search" value="&key=${param.key}&query=${param.query}"/>
        </c:if>


 		<div class="pagination-area">


                <ul class="pagination">

                    <!-- 첫 페이지로 이동 -->
                    <li><a href="/board/${boardCode}?cp=1${search}">&lt;&lt;</a></li>

                    <!-- 이전 목록 마지막 번호로 이동 -->
                    <li><a href="/board/${boardCode}?cp=${pagination.prevPage}${search}">&lt;</a></li>


                    <!-- 특정 페이지로 이동 -->
                    <c:forEach var="i" begin="${pagination.startPage}"
                                end="${pagination.endPage}" step="1">
                        <c:choose>
                           <c:when test="${i== pagination.currentPage}">
                                <!-- 현재 보고있는 페이지 -->
                                <li><a class="current">${i}</a></li>
                           </c:when>

                           <c:otherwise>
                                <!-- 현재 페이지를 제외한 나머지 -->
                                <li><a href="/board/${boardCode}?cp=${i}${search}">${i}</a></li>
                           </c:otherwise>
                        </c:choose>
                    </c:forEach>

                    <!-- 다음 목록 시작 번호로 이동 -->
                    <li><a href="/board/${boardCode}?cp=${pagination.nextPage}${search}">&gt;</a></li>

                    <!-- 끝 페이지로 이동 -->
                    <li><a href="/board/${boardCode}?cp=${pagination.maxPage}${search}">&gt;&gt;</a></li>

                </ul>
            </div>




			<!-- 검색창 -->
            <form action="${boardCode}" method="get" id="boardSearch">

                <select name="key" id="searchKey">
                    <option value="t">제목</option>
                    <option value="c">내용</option>
                    <option value="tc">제목+내용</tion>
                    <option value="w">작성자</option>
                </select>

                <input type="text" name="query"  id="searchQuery" placeholder="검색어를 입력해주세요.">

                <button>검색</button>
            </form>

🫧 boardList.java

// 검색창 이전의 기록 남겨 놓기 
const boardSearch = document.querySelector("#boardSearch");
const searchKey = document.querySelector("#searchKey");
const searchQuery = document.querySelector("#searchQuery");
const options = document.querySelectorAll("#searchKey > option");

(()=>{
    const params = new URL(location.href).searchParams;
    const key = params.get("key"); //t,c,tc,w중  하나
    const query = params.get("query"); // 검색어

    if(key != null){ // 검색을 했을 때
        searchQuery.value=query; // 검색어를 화면에 출력 
    
        // option태그를 하나씩 순차접근해서 value가 key랑 같으면
        // selected속성 추가
        for(let op of options){
            if(op.value == key){
                op.selected = true;
            }

        }
    }
})();

//검색어 없이 제출된 경우 
boardSearch.addEventListener("submit", e =>{
    if(searchQuery.value.trim().length == 0){
        e.preventDefault();

        location.pathname//해당게시판 1페이지로 이동 

        //location.pathname : 쿼리스트링을 제외한 실제 주소
    }
})

🫧 boardController.java

if문으로 게시글 검색이 있을 경우와 없을 경우를 만들어 주었다

	//게시글 목록 조회
	@GetMapping("/{boardCode:[0-9]+}") // boardCode는 1자리 이상 숫자
	public String selectBoardList(@PathVariable("boardCode") int boardCode
			, @RequestParam(value="cp", required = false, defaultValue = "1") int cp
			, Model model
			, @RequestParam Map<String, Object> paramMap //파라미터가 전부다 담겨 있음 
			) {
		
		// boardCode 확인
		//System.out.println("boardCode: "+ boardCode);
		
		if( paramMap.get("key") == null ) {//검색어가 없을 때 
			
			// 게시글을 목록 조회하는 service호출 
			Map<String, Object> map = service.selectBoardList(boardCode, cp);
			
			//조회 결과를 request scope에 세팅 후 forward
			model.addAttribute("map", map);

		}else { //검색어가 있다 (검색 O)
			
			paramMap.put("boardCode", boardCode);
			
			Map<String , Object> map = service.selectBoardList(paramMap, cp);
			
			model.addAttribute("map", map);
		}
		return "board/boardList";
	}

🫧 boardService.java

	/** 검색어를 통한 게시글 목록 조회(검색)
	 * @param paramMap
	 * @param cp
	 * @return boardList
	 */
	Map<String, Object> selectBoardList(Map<String, Object> paramMap, int cp);

🫧 boardServiceImpl.java

매개변수의 자료형이 달라서 overlodding되어 메소드 사용할 수 있다!

	// 게시글 목록 조회 (검색)
	@Override
	public Map<String, Object> selectBoardList(Map<String, Object> paramMap, int cp) {

		// 1. 특정 게시판에 삭제되지 않고 검색 조건이 일치하는 게시글 수 조회
		int listCount = dao.getListCount(paramMap);

		// 2. 1번 조회 결과 + cp를 이용해서 Pagination 객체 생성
		// -> 내부에 필드가 모두 계산 되어서 초기화 됨
		Pagination pagination = new Pagination(cp, listCount);


		// 3. 특정게시판에서
		// 현재 페이지에 해당하는 게시글 목록 조회
		// + 단, 검색 조건이 일치하는 글만 
		List<Board> boardList = dao.selectBoardList(pagination, paramMap);

		// 4. paginatio, boardList를 Map에 담아서 반환
		Map<String, Object> map = new HashMap<String, Object>();

		map.put("pagination", pagination);
		map.put("boardList", boardList);

		return map;
	}

🫧 boardDAO.java

	/** 게시글 수 조회(검색)
	 * @param paramMap
	 * @return listCount
	 */
	public int getListCount(Map<String, Object> paramMap) {
		return sqlSession.selectOne("boardMapper.getListCount_search", paramMap);
	}


	/** 게시글 목록 조회(검색)
	 * @param pagination
	 * @param paramMap
	 * @return boardList
	 */
	public List<Board> selectBoardList(Pagination pagination, Map<String, Object> paramMap) {
		
		// 1) offset 계산
		int offset 
		= (pagination.getCurrentPage() -1) * pagination.getLimit();

		// 2) Row Bounds객체 생성
		RowBounds rowBounds = new RowBounds(offset, pagination.getLimit());

		// 3) selectList("namespace.id", 파라미터, Rowbounds)호출
		return sqlSession.selectList("boardMapper.selectBoardList_search", paramMap, rowBounds);
	}

🫧 board-mapper.xml

동적 SQL사용을 사용하여 조회해 보았다(if, choose,CDATA)

	<!-- 특정게시판에 삭제되지 않고 검색 조건에 일치하는 게시글 수 조회 -->
	<select id="getListCount_search"  resultType="_int">
		SELECT COUNT(*)
		FROM BOARD
		
		<!-- 작성자 검색일 경우 -->
		<if test='key=="w"'>
			JOIN MEMBER USING(MEMBER_NO)
		</if>
		
		WHERE BOARD_DEL_FL = 'N'
		AND BOARD_CODE = #{boardCode}
		
		
		<choose>
			<when test='key== "t"'>
				<!-- 제목 -->
				AND BOARD_TITLE LIKE '%${query}%'
			</when>
			<when test='key=="c"'>
				<!-- 내용 -->
				AND BOARD_CONTENT LIKE '%${query}%'
			</when>
			<when test='key=="tc"'>
				<!-- 제목 + 내용 -->
				AND (BOARD_TITLE LIKE '%${query}%' OR BOARD_CONTENT LIKE '%${query}%')
			</when>
			<when test='key=="w"'>
				<!-- 작성자(닉네임) -->
				AND MEMBER_NICKNAME LIKE '%#{query}%'			
			</when>
		</choose>		
	</select>
	
	<!-- CDATA 태그 : 해당 태그 내부에 작성된 것은 모두 문자로 취급-->
	<!-- 게시글 목록 조회 -->
	<select id="selectBoardList_search" resultMap="board_rm">
		SELECT BOARD_NO, BOARD_TITLE, MEMBER_NICKNAME, READ_COUNT, 
         
         <![CDATA[
            CASE  
               WHEN SYSDATE - B_CREATE_DATE < 1/24/60
               THEN FLOOR( (SYSDATE - B_CREATE_DATE) * 24 * 60 * 60 ) || '초 전'
               WHEN SYSDATE - B_CREATE_DATE < 1/24
               THEN FLOOR( (SYSDATE - B_CREATE_DATE) * 24 * 60) || '분 전'
               WHEN SYSDATE - B_CREATE_DATE < 1
               THEN FLOOR( (SYSDATE - B_CREATE_DATE) * 24) || '시간 전'
               ELSE TO_CHAR(B_CREATE_DATE, 'YYYY-MM-DD')
            END B_CREATE_DATE,
         ]]>
         
         (SELECT COUNT(*) FROM "COMMENT" C
          WHERE C.BOARD_NO = B.BOARD_NO) COMMENT_COUNT,
          
         (SELECT COUNT(*) FROM BOARD_LIKE L
          WHERE L.BOARD_NO = B.BOARD_NO) LIKE_COUNT,
          
         (SELECT IMG_PATH || IMG_RENAME FROM BOARD_IMG I
         WHERE I.BOARD_NO = B.BOARD_NO
         AND IMG_ORDER = 0) THUMBNAIL
      FROM "BOARD" B
      JOIN "MEMBER" USING(MEMBER_NO)
      WHERE BOARD_DEL_FL = 'N'
      AND BOARD_CODE = #{boardCode}
      
      <choose>
			<when test='key== "t"'>
				<!-- 제목 -->
				AND BOARD_TITLE LIKE '%${query}%'
			</when>
			<when test='key=="c"'>
				<!-- 내용 -->
				AND BOARD_CONTENT LIKE '%${query}%'
			</when>
			<when test='key=="tc"'>
				<!-- 제목 + 내용 -->
				AND (BOARD_TITLE LIKE '%${query}%' OR BOARD_CONTENT LIKE '%${query}%')
			</when>
			<when test='key=="w"'>
				<!-- 작성자(닉네임) -->
				AND MEMBER_NICKNAME LIKE '%#{query}%'			
			</when>
		</choose>
      
      ORDER BY BOARD_NO DESC
	</select>
profile
나를 죽이지 못하는 오류는 내 코드를 더 강하게 만들지ㅋ
post-custom-banner

0개의 댓글