SQL 형식
and name like '%철수%'
and content like '%철수%'
and title like '%철수%'
mapper 에서
#이 아니라 $ 은
ex) where idx >0 and ${search_option} like '%' || #{search} || '%'
자동적으로 마이바티스에서 #을 쓰면 자동적으로 '' 가들어가지만
$ 은 생략 된다.
오라클에서 || 은 앞과 뒤를 연결 하라는 의미이다. 또는 mysql
CONCAT ('%' , #{search}, '%') 은 같은 의미이다.
@RequestMapping(value="/board_list.do", method=RequestMethod.GET)
public String board_list(@RequestParam(defaultValue="1") int curPage,
@RequestParam(required=false, defaultValue="name")
String search_option,
@RequestParam(required=false, defaultValue="")
String search,
Model model){
//@RequestParam 지정된 변수값이 넘어오지 않으면 400에러
//required=false 필수 항목이 아님, 기본값은 required=true
//defaultValue ="기본값"
뷰
에서 selectd 값을 적용 하는 방법에 주의 깊게 살펴 보자
<!-- 검색폼 -->
<form method="get" action="/board/listPage" >
<select name="searchType">
<option value="" <c:out value="${ param.searchType eq null ? 'selected' : '' }" /> >
선택 </option>
<option value="userid" <c:out value="${ param.searchType eq 'userid' ? 'selected' : '' }" /> >아이디</option>
<option value="username" <c:out value="${ param.searchType eq 'username' ? 'selected' : '' }" /> >글쓴이</option>
<option value="subject" <c:out value="${ param.searchType eq 'subject' ? 'selected' : '' }" /> >제목</option>
<option value="content" <c:out value="${ param.searchType eq 'content' ? 'selected' : '' }" /> >내용</option>
<option value="all" <c:out value="${ param.searchType eq 'all' ? 'selected' : '' }" /> >전체</option>
</select>
<input type="text" name="keyword" value="${param.keyword }" ><button type="submit" class="btn btn-info">검색</button>
</form>
Mybatis에서 if 문 사용에 null 값이 넘겨 오면 sql 오류가 나오므로
처음에는 단순하게 코딩을 하자. 따옴표 에 주의 하자.
#{keyword} 에 따옴펴가 없다.
# 이 아니라 ${searchType} 사용 했다.
Mabatis 에서 공통 부분에 적용할 코드는 <sql> 사용하면 코드 양이 줄어 든다.
<sql id="search">
<if test="searchType !=null" >
<if test="searchType == 'userid' || searchType == 'username' || searchType == 'subject' || searchType == 'content'">
and ${searchType} like concat('%', #{keyword}, '%')
</if>
</if>
<if test="searchType== 'all' ">
and ( userid like concat('%', #{keyword} , '%')
or username like concat('%', #{keyword} , '%')
or subject like concat('%', #{keyword} , '%')
or content like concat('%', #{keyword} , '%')
)
</if>
</sql>
<select id="pageTotalCountSearch" resultType="int">
select count(*) from board_v where idx > 0
<include refid="search"></include>
</select>
<select id="listCriteraSearch" resultType="BoardDTO">
select * from board_v
where idx > 0
<include refid="search"></include>
order by ref desc, reorder asc limit #{pageStart} , #{perPageNum}
</select>
검색 개발에서 중요한 것은
전체 갯수 에서 반드시 키워드와 타입에 대한 파라미터가 들어가 하며.
리스트에서 데이터를 가져 올때도 키워드 와 검색 타입의 파라미터가 추가가 필요하다.
1. 첫번째 방법
SearchCriteria 클래스를 생성하지 않고 UriComponetBuilder 사용하지 않으면
코드 가 복잡 해 진다. 특히 view 에서 페이징 href 처리시 복잡해 질 수 있다.
//MYSQL
@RequestMapping(value="/listPage", method=RequestMethod.GET)
public void listPage(Criteria cri,
@RequestParam(required=false) String searchType,
@RequestParam(required=false) String keyword,
Model model) throws Exception{
PageMaker pageMaker =new PageMaker();
pageMaker.setCri(cri);
logger.info(" searchType : " + searchType + " keyword : " + keyword);
//페이지 총 개수 가져오기
int count =boardService.pageTotalCountSearch(searchType, keyword);
logger.info(" /페이지 총 개수count " + count );
pageMaker.setTotalCount(count);
model.addAttribute("list", boardService.listCriteraSearch(cri, searchType, keyword ));
model.addAttribute("searchType", searchType);
model.addAttribute("keyword", keyword);
model.addAttribute("pageMaker", pageMaker);
}
DAO 에서 처리
@Override
public List<BoardDTO> listCriteraSearch(Criteria cri, String searchType, String keyword) {
Map<String, Object> map =new HashMap<>();
map.put("pageStart", cri.getPageStart());
map.put("perPageNum", cri.getPerPageNum());
map.put("searchType", searchType);
map.put("keyword", keyword);
return sqlSession.selectList(namespace +".listCriteraSearch" , map);
}
뷰에서 페이징 처리
<div class="pagination">
<ul>
<c:if test="${ param.page > 1}">
<li><a href="/board/listPage${ pageMaker.makeQuery(1) }&searchType=${param.searchType }&keyword=${param.keyword }">[시작]</a></li>
</c:if>
<c:if test="${ pageMaker.prev }">
<li><a href="/board/listPage${ pageMaker.makeQuery(pageMaker.startPage - 1) }&searchType=${param.searchType }&keyword=${param.keyword }">«</a></li>
</c:if>
<c:forEach begin="${ pageMaker.startPage }" end="${ pageMaker.endPage }" step="1" var="pageNum">
<c:choose>
<c:when test="${ pageMaker.cri.page == pageNum }">
<li class="active">
<a href="/board/listPage${pageMaker.makeQuery(pageNum) }&searchType=${param.searchType }&keyword=${param.keyword }" style="background:#E85356; color:white; ">${pageNum }</a>
</li>
</c:when>
<c:otherwise>
<li>
<a href="/board/listPage${pageMaker.makeQuery(pageNum) }&searchType=${param.searchType }&keyword=${param.keyword }">${pageNum }</a>
</li>
</c:otherwise>
</c:choose>
</c:forEach>
<c:if test="${pageMaker.next && pageMaker.endPage > 0 }" >
<li><a href="/board/listPage${pageMaker.makeQuery(pageMaker.endPage + 1) }&searchType=${param.searchType }&keyword=${param.keyword }">»</a></li>
</c:if>
<!-- 마지막 페이지 -->
<c:if test="${ param.page < pageMaker.tempEndPage}">
<li><a href="/board/listPage${ pageMaker.makeQuery(pageMaker.tempEndPage) }&searchType=${param.searchType }&keyword=${param.keyword }">[끝]</a></li>
</c:if>
</ul>
</div>
1. 두번째 방법
UriComponentsBuilder 사용
@Data
public class SearchCriteria extends Criteria{
private String searchType;
private String keyword;
}
컨트롤
//MYSQL
@RequestMapping(value="/listPage", method=RequestMethod.GET)
public void listPage(SearchCriteria cri, Model model) throws Exception{
PageMaker pageMaker =new PageMaker();
pageMaker.setCri(cri);
logger.info(" searchType : " + cri.getSearchType() + " keyword : " + cri.getKeyword());
//페이지 총 개수 가져오기
int count =boardService.pageTotalCountSearch(cri);
logger.info(" /페이지 총 개수count " + count );
pageMaker.setTotalCount(count);
model.addAttribute("list", boardService.listCriteraSearch(cri);
model.addAttribute("pageMaker", pageMaker);
}
페이지 메이커 클래스에 추가 메소드
public String makeSearch(int page){
UriComponents uriComponents =
UriComponentsBuilder.newInstance()
.queryParam("page", page)
.queryParam("perPageNum", cri.getPerPageNum())
.queryParam("searchType", ((SearchCriteria)cri).getSearchType())
.queryParam("keyword", ((SearchCriteria)cri).getKeyword())
.build();
return uriComponents.toUriString();
}
dao
@Override
public List<BoardDTO> listCriteraSearch(SearchCriteria cri) {
return sqlSession.selectList(namespace +".listCriteraSearch" , cri);
}
뷰에서 페이징 처리
<div class="pagination">
<ul>
<c:if test="${ param.page > 1}">
<li><a href="/board/listPage${ pageMaker.makeSearch(1) }">[시작]</a></li>
</c:if>
<c:if test="${ pageMaker.prev }">
<li><a href="/board/listPage${ pageMaker.makeSearch(pageMaker.startPage - 1) }">«</a></li>
</c:if>
<c:forEach begin="${ pageMaker.startPage }" end="${ pageMaker.endPage }" step="1" var="pageNum">
<c:choose>
<c:when test="${ pageMaker.cri.page == pageNum }">
<li class="active">
<a href="/board/listPage${pageMaker.makeSearch(pageNum) }" style="background:#E85356; color:white; ">${pageNum }</a>
</li>
</c:when>
<c:otherwise>
<li>
<a href="/board/listPage${pageMaker.makeSearch(pageNum) }">${pageNum }</a>
</li>
</c:otherwise>
</c:choose>
</c:forEach>
<c:if test="${pageMaker.next && pageMaker.endPage > 0 }" >
<li><a href="/board/listPage${pageMaker.makeSearch(pageMaker.endPage + 1) }">»</a></li>
</c:if>
<!-- 마지막 페이지 -->
<c:if test="${ param.page < pageMaker.tempEndPage}">
<li><a href="/board/listPage${ pageMaker.makeSearch(pageMaker.tempEndPage) }">[끝]</a></li>
</c:if>
</ul>
</div>
댓글 ( 4)
댓글 남기기