페이징 까지 구현했으니 이제 중요한 기능중에 하나인 검색 기능을 추가하겠습니다.

저희는 페이징 처리하는 부분에서 많은 기능들을 처리하였는데요~

Criteria, PageMaker VO에서 makeQuery 메서드 기억하시나요?

makeQuery 부분에 두 가지 속성을 추가하겠습니다!

 

- searchType : 검색 타입

 

- keyword : 검색어

 

이제 구현해보겠습니다!

 

Criteria, PageMaker 수정

 

검색을 했을 때 검색 결과에 따른 정보를 게시물을 삭제, 등록, 수정, 조회 후에도 그대로 유지하려면 

URI에 searchType, keyword를 달고 다녀야합니다! 

페이징처리에서 사용했던 page와 perPageNum처럼요!

 

package kr.co.web.domain;

import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;

public class Criteria {
	
	private int page;
	private int perPageNum;
	private String searchType;
	private String keyword;
	
	public Criteria() {
		// TODO Auto-generated constructor stub
		this.page = 1;
		this.perPageNum = 10;
		this.searchType = null;
		this.keyword = null;
	}
    
        // getter, setter 생략
	
	public String makeQuery() {
		UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.newInstance()
				.queryParam("page", this.page)
				.queryParam("perPageNum", this.perPageNum);
		
		if(searchType != null) {
			uriComponentsBuilder
				.queryParam("searchType", this.searchType)
				.queryParam("keyword", this.keyword);
		}
		return uriComponentsBuilder.build().encode().toString();
	}
	
	@Override
	public String toString() {
		return "Criteria [page=" + page + ", perPageNum=" + perPageNum + "]";
	}
	
	
}

 

 

makeQuery메서드에서 if(searchType != null) 이게 조건을 준 이유는요

사용자가 검색을 하지도 않았는데 굳이 searchType과 keyword를 가지고 갈 필요가 없기때문에 조건을 주었습니다.

 

PageMaker의 makeQuery도 수정하겠습니다!

 

package kr.co.web.domain;

import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;

public class PageMaker {
	
	private int displayPageCnt = 10; // 화면에 보여질 페이지 번호 수
	private int totalDataCount; // 실제 게시물 수
	private int startPage; // 현재 페이지 기준 시작 페이지 번호 
	private int endPage; // 현재 페이지 기준 끝 페이지 번호
	private boolean prev; // 이전 버튼 활성화 여부
	private boolean next; // 다음 버튼 활성화 여부
	private Criteria cri; //page(현재 페이지), perPageNum(페이지 당 보여질 게시물의 수)
	private int finalPage; // 맨끝
	private int firstPage; // 맨처음
	
	public PageMaker(Criteria cri) {
		this.cri = cri;
	}
	
	
	public int getDisplayPageCnt() {
		return displayPageCnt;
	}
	
	public void setDisplayPageCnt(int displayPageCnt) {
		this.displayPageCnt = displayPageCnt;
	}
	
	public int getTotalDataCount() {
		return totalDataCount;
	}

	public void setTotalDataCount(int totalDataCount) {
		this.totalDataCount = totalDataCount;
		calcData();
	}
	
	//startPagem endPage, prev, next, firstPagem finalPage 계산
	public void calcData() {
		int page = this.cri.getPage();
		int perPageNum = this.cri.getPerPageNum();
		
		// 현재 페이지가 2면 2/10 = 0.2 Math.ceil객체를 이용하여 무조건 올림 하면 1 * displayPageCnt = 10
		this.endPage = (int)(Math.ceil(page / (double)displayPageCnt) * displayPageCnt);
		
		// endPage - 화면에 보여줄 페이지수를 한뒤 + 1을 하면 된다. 
		this.startPage = (this.endPage - displayPageCnt) + 1;
		
		// 전체 게시물 수를 통한 endPage 
		// 데이터가 89 개면 9페이지까지 출력
		int tempEndPage = (int)(Math.ceil(totalDataCount / (double)perPageNum));
		
		if(this.endPage > tempEndPage) {
			this.endPage = tempEndPage;
		}
		
		this.prev = startPage == 1? false : true;
		this.next = (endPage * perPageNum) <= totalDataCount ? true : false;
		
		// 맨끝
		// +1하는 이유는 저렇게 계산하면 맨끝에서 2번째 페이지가 출력되기때문.
		this.finalPage = (int)(Math.ceil(totalDataCount / perPageNum)+1);
						
		// 맨처음
		this.firstPage = 1;
	}
	
	public String makeQuery(int page) {
		UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.newInstance()
				.queryParam("page", page)
				.queryParam("perPageNum", this.cri.getPerPageNum());
		
		if(this.cri.getSearchType() != null) {
			uriComponentsBuilder
				.queryParam("searchType", this.cri.getSearchType())
				.queryParam("keyword", this.cri.getKeyword());
		}
		return uriComponentsBuilder.build().encode().toString();
	}
	
	
	
}

 

 

boardMapper.xml 수정

 

검색을 하기 위해 다음과 같이 select 박스를 구현하겠습니다.

 

 

listPage.jsp

<div class="container">
	<select id="searchTypeSel" name="searchType">
		<option value="">검색조건</option>
		<option value="t">제목</option>
		<option value="c">내용</option>
		<option value="w">작성자</option>
		<option value="tc">제목+내용</option>
		<option value="all">전체조건</option>
	</select>
		
	<input type="text" id="keyword" name="keyword" value="${pageMaker.cri.keyword}" placeholder="검색어를 입력하세요"/>
	<button id="searchBtn" class="btn btn-primary">검색</button>
</div>

 

 

만약 제목에 슥이 라는 게시물을 검색하려면 다음과 같이 쿼리문을 작성하여 mysql 서버에 있는 blog 테이블에서 데이터를 조회해와야 합니다.

 

select *
from board
where title like CONCAT ('%', '슥이', '%')
order by board_number desc, create_date desc
limit #{dataStart}, #{perPageNum}

 

이렇게 검색의 타입마다 쿼리문을 작성하려면 복잡하기도 하고 노가다 입니다.

이럴 때 MyBatis에서 제공하는 if문을 사용하면 검색 조건에 따른 동적 sql문을 손쉽게 추가해줄 수 있습니다.

 

기존의 listPage 쿼리를 수정해보겠습니다.

 

<!-- board 페이징 조회 -->
	<select id="listPage" resultType="BoardVO">
		select *
		from board
		<if test="searchType != null">
		
			<if test="searchType == 't'.toString()">
				where title like CONCAT('%', #{keyword}, '%')
			</if>
			
			<if test="searchType == 'c'.toString()">
				where contents like CONCAT('%', #{keyword}, '%')
			</if>
			
			<if test="searchType == 'w'.toString()">
				where name like CONCAT('%', #{keyword}, '%')
			</if>
			
			<if test="searchType == 'all'.toString()">
				where title like CONCAT('%', #{keyword}, '%')
					or contents like CONCAT('%', #{keyword}, '%')
					or name like CONCAT('%', #{keyword}, '%')
			</if>
			
		</if>
		order by board_number desc, create_date desc
		limit #{dataStart}, #{perPageNum}
	</select>

 

이렇게 작성했는데 생각해보니 검색된 결과에 따라 페이지 번호도 달라지기 때문에 전체 게시물 수를 구하는

totalCount 쿼리도 수정해주어야 하는데 위와 같이 추가하기에는 코드가 중복이 되기 때문에

<sql>과 <include>를 사용하겠습니다.

 

<sql>이란 쉽게 설명을 하자면 원터치 텐트라고 생각하시면 됩니다.

<include>는 원터치 텐트를 던지면 알아서 텐트가 쳐지듯이 include태그를 작성하면 펴진다 라고 이해하시면 됩니다!

 

<!-- 검색 -->
	<sql id="searchCondition">
		<if test="searchType != null">
		
			<if test="searchType == 't'.toString()">
				where title like CONCAT('%', #{keyword}, '%')
			</if>
			
			<if test="searchType == 'c'.toString()">
				where contents like CONCAT('%', #{keyword}, '%')
			</if>
			
			<if test="searchType == 'w'.toString()">
				where name like CONCAT('%', #{keyword}, '%')
			</if>
			
			<if test="searchType == 'all'.toString()">
				where title like CONCAT('%', #{keyword}, '%')
					or contents like CONCAT('%', #{keyword}, '%')
					or name like CONCAT('%', #{keyword}, '%')
			</if>
			
		</if>
	</sql>
	
	<!-- board 페이징 조회 -->
	<select id="listPage" resultType="BoardVO">
		select *
		from board
		<include refid="searchCondition"></include>
		order by board_number desc, create_date desc
		limit #{dataStart}, #{perPageNum}
	</select>
    
    <!-- 전체 데이터 구하기 -->
	<select id="totalCount" resultType="int">
		select count(board_number)
		from board
		<include refid="searchCondition"></include>
	</select>

 

그리고 boardDAO의 listPage 메서드와 totalCount 메서드 둘 다 Criteria를 매개변수로 받았기 때문에

boardMapper까지 searchType과 keyword가 무사히 전달된 것입니다.

'JAVA > blog' 카테고리의 다른 글

jQuery .val() - form의 값을 가져거나 값을 설정하는 메서드  (0) 2020.07.23
검색(2)  (0) 2020.07.23
페이징 처리(5)  (0) 2020.07.19
페이징 처리(4)  (0) 2020.07.16
페이지 처리(3)  (0) 2020.07.16

+ Recent posts