** Paging과 이어지는 내용입니다
- 클라이언트가 검색어를 입력하면 DB에서 검색어가 포함된 Row를 SELECT
- 검색어를 어떤 컬럼에서 찾는지 설정
1. '%검색어%' 형태로 만들기
1) 쿼리문에 연결연산자 활용
2) getter를 통해 % 붙이기
2. 검색할 컬럼마다 SQL을 설정
- 동적SQL 사용
3. 페이지를 넘길 때 검색기준, 검색어를 같이 넘기게 설계
4. 검색기준, 검색어에 맞게 총 갯수를 수정
- 자세한 과정은 설명 참고
설명1. JSP 만들기
<div class="search_container">
<form action="./list" method="get">
<fieldset>
<select name="kind">
<option value="col1">제목</option>
<option value="col2">내용</option>
<option value="col3">작성자</option>
</select>
<input type="text" name="search" value="${pager.search}">
<button type="submit">검색</button>
</fieldset>
</form>
</div>
우선, 어제 했던 Pager에서 추가로 생각을 해보아야 한다.
검색을 위해 처음으로 생각해 보아야 할 것이,
어떤 파라미터가 필요할지를 생각해보아야 한다.
우선, 뭘 기준으로 검색할건지이다.
뭐 제목으로 검색할건지, 내용으로 검색할건지, 작성자로 검색할건지를 판단해서,
검색할 컬럼(기준)은 파라미터 이름을 kind로 하고 select 태그를 통해 만들었다.
value는 각각 col1, 2, 3 로 해놨는데 이따가 kind를 세팅할 때 사용할 것이다.
그리고 검색어는 파라미터 이름을 search로 해놓았다.
그리고, 사용자가 검색을 한 이후에는 텍스트박스에 이전 검색어가 표시될 수 있도록,
Pager 객체에서 search변수를 가져와 value 값에 넣어놓았다.
Pager 객체에 왜 search 변수가 있는지는 설명 2번을 참조하면 답이 나올 것이다.
설명2. 검색어 설정하기
자, JSP를 만든 다음에 자바로 넘어왔다.
우선, JSP에서 파라미터를 넘겨주면, 매퍼에서 그 파라미터를 받아 쿼리문에 넘겨주어야 하지 않겠는가?
그리고 그 검색어가 포함된 Row를 찾기 위해 조건절에 Like %검색어%를 추가해야 한다.
검색어는 search로 받는다고 했다. 그러면 최종적으로 쿼리문을
<select id="list" parameterType="Pager" resultType="BankBookDTO">
SELECT *
FROM (SELECT ROWNUM R, B.*
FROM (SELECT * FROM BANKBOOK
WHERE BOOKNUMBER > 0 AND BOOKNAME LIKE #{search}
ORDER BY BOOKNUMBER DESC) B)
WHERE R BETWEEN #{startRow} AND #{lastRow}
</select>
위와 같이 수정해야 할 것이다.
유의해야할 점은 순서를 잘 고려해야 한다.
검색이 이미 된 테이블을 기준으로 startRow와 lastRow 조건을 주어서
또 SELECT를 진행 하는 것이기 때문에 서브쿼리 안에 조건을 추가해야 한다.
자, 근데 우리가 파라미터로는 하나의 데이터타입만 받을 수 있었다.
우리가 페이징 처리를 할 때 startRow와 lastRow를 매퍼로 보내기 위해서
Pager 클래스에 startRow와 lastRow를 멤버변수로 선언했었다.
그렇다면, kind와 search도 마찬가지로 Pager 클래스의 멤버변수로 추가해주어야 한다.
마이바티스에서는 만약 파라미터가 String이면 알아서 ' '를 추가해준다.
그래서 '%#{search}%' 와 같이 작성하면 오류가 난다.
만약 search에 10을 넣었다고 치자, 그럼 마이바티스에서 자동으로 '10' 을 만들어준다,
그럼 Like '%'10'%' 이 되는 셈이다, 이러면 쿼리문의 문법에 맞지 않게 된다.
무조건 '%검색어%' 형식을 맞추어 주어야 한다.
하나의 방법은 연결연산자 || 를 이용하는 방법이다. '%' || '10' || '%' 를 사용하면 모두 더해주게 된다.
즉, '%' || #{search} || '%' 를 사용하면 된다. 그러면, '%search%' 가 되게 된다.
또 다른 방법은 getter 메서드를 이용하는 방법이다.
#{search} 를 하면, Pager 객체의 search게터를 호출하게 되는 셈이다.
그렇다면, 게터를 이용해서 %를 앞뒤로 붙여주면 되는 것 아닌가?
public String getSearch() {
// 검색어가 없으면 search = null, 기본값을 넣어야 함
if(this.search == null) {
this.search = "";
}
this.search = "%" + this.search + "%";
return search;
}
근데, 게터를 사용하면 안좋은 점은, 위의 설명1번에서
사용자가 검색을 한 다음에, 검색어 입력창에 이전 검색어를 표현해주기 위해
value 값에 pager.search 를 통해 Pager 객체에 저장된 search 멤버변수를 출력해 주었었다.
근데 게터를 통해 %를 붙여버리면,
search의 값이 항상 앞 뒤로 %가 붙어 있는 상태로 나오기 때문에,
사용자가 search의 값으로 입력한 값에 %가 붙어서 나온 상황이 된다.
그래서 차라리 연결연산자를 통해 쿼리문을 수정하는 방식이 좋다.
자, 이제 search는 사용했으니 kind를 활용해보자.
그냥 WHERE절의 컬럼명 자리에 #{kind}를 쓰면 될 것 같아 보인다.
근데 문제는, #{ } 는 Data만 가능이다, 테이블명이나 컬럼명에는 사용 불가능이다.
조건절의 조건에 들어가는 데이터라던지 그런 값에만 #{ } 을 사용할 수 있다.
FROM절의 테이블명이나, WHERE절의 컬럼명 등에는 사용 불가능 하다.
아니 그러면 컬럼명마다 쿼리문을 만들고 DAO의 메서드도 따로 만들어야하고
그렇게 해야하는가? 그건 또 아니다. 마이바티스에서 해결책을 제시해놓고 있다.
이제 그 해결책을 알아보러 가자
설명3. 어느 컬럼에서 조회할 것인지 설정하기
해결책은 바로 동적 SQL을 사용하면 된다. (44일차 동적SQL글 참고)
<select id="list" parameterType="Pager" resultType="BankBookDTO">
SELECT *
FROM (SELECT ROWNUM R, B.*
FROM (SELECT * FROM BANKBOOK
WHERE BOOKNUMBER > 0
AND
<choose>
<when test="kind=='col1'">
BOOKNAME
</when>
<otherwise>
BOOKCONTENTS
</otherwise>
</choose>
LIKE '%'||#{search}||'%'
ORDER BY BOOKNUMBER DESC) B)
WHERE R BETWEEN #{startRow} AND #{lastRow}
</select>
설명4. 페이지를 넘길 때 검색기준, 검색어를 같이 넘기게 설계
우리가 paging 처리를 할 때,
페이지 번호를 누르면 kind와 search를 파라미터로 넘기지 않았기 때문에
JSP에서 이거를 넘겨주어야 한다.
그래서 이걸 수정해주면 된다.
<c:forEach begin="${pager.startNum}" end="${pager.lastNum}" var="i" >
<a href="./list?page=${i}&kind=${pager.kind}&search=${pager.search}">${i}</a>
</c:forEach>
Pager 객체에 있는 kind와 Pager 객체에 있는 search 변수를
페이지를 누를 때 마다 (요청을 보낼 때마다) 파라미터로 보내게 하여서
사용자가 입력했던 검색 기준, 검색어를 가지고 다음페이지로 넘어가도록 설계하는 것이다.
설명5. 총 갯수를 수정
검색기준과 검색어를 가지고 검색된 데이터의 총 갯수를 가져와야하기 때문에,
totalCount를 가져오는 SQL문을 수정해야 한다.
<select id="total" resultType="Long" parameterType="Pager">
SELECT COUNT(BOOKNUMBER) FROM BANKBOOK
WHERE BOOKNUMBER > 0
AND
<choose>
<when test="kind=='col1'">
BOOKNAME
</when>
<otherwise>
BOOKCONTENTS
</otherwise>
</choose>
LIKE '%'||#{search}||'%'
</select>
이렇게 조건을 바꿔준다음에, 이제는 이 총 갯수를 조회하는 SQL문도
파라미터가 필요하기 때문에, 파라미터 타입을 Pager로 받아준다.
그러면 DAO에서도 Pager가 필요하게 되고, Service에서도 결국 매개변수로 Pager를 줘야한다는 소리이다.
각각 알아서 Pager 객체를 넣어주면 된다 (굳이 설명 안해도 이제는 뭔말인지 알 것이다)
여기까지가 검색기능의 최종이다.
'웹개발 풀스택 과정 > Spring Legacy' 카테고리의 다른 글
45일차(2022.03.02) _ link 태그의 요청을 처리하는 과정 (0) | 2022.03.02 |
---|---|
44일차(2022.02.25) _ MyBatis - 동적 SQL (0) | 2022.02.25 |
43일차(2022.02.24) _ 페이징(Paging) 처리 기본 - JSP 표시 (0) | 2022.02.24 |
43일차(2022.02.24) _ 페이징(Paging) 처리 기본 - SQL, Java 에서 처리 (0) | 2022.02.24 |
41일차(2022.02.22) _ EL 연산자, ESTL제어문 (0) | 2022.02.22 |