MyBatis는 SQL을 그대로 사용할 수 있기 때문에 인라인뷰를 이용하는 SQL을 작성하고, 필요한 파라미터를 지정하는 방식으로 페이징 처리를 하게 된다. 여기서 신경 써야 하는 점은 페이징 처리를 위해서는 SQL을 실행할 때 몇 가지 파라미터가 필요하다는 점이다. 페이징 처리를 위해서 필요한 파라미터는 1) 페이지 번호, 2) 한 페이지당 몇 개의 데이터를 보여줄 것인지가 결정되어야만 한다.
페이지 번호와 몇 개의 데이터가 필요한지를 별도의 파라미터로 전달하는 방식도 나쁘지는 않지만, 아예 이 데이터들을 하나의 객체로 묶어서 전달하는 방식이 나중을 생각하면 좀 더 확장성이 좋다.
1) org.zerock.domain 패키지에 Criteria 이름의 클래스를 작성한다. (이는 검색의 기준을 의미한다.)
package org.zerock.domain;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@ToString
public class Criteria {
private int pageNum;
private int amount;
public Criteria() {
this(1,10);
}
public Criteria(int pageNum, int amount) {
this.pageNum = pageNum;
this.amount = amount;
}
}
Criteria 클래스의 용도는 pageNum과 amount 값을 같이 전달하는 용도지만 생성자를 통해서 기본값을 1페이지, 10개로 지정해서 처리한다. Lombok을 이용해서 getter/setter을 생성해준다.
1. MyBatis 처리와 테스트
BoardMapper는 인터페이스와 어노테이션을 이용하기 때문에 페이징 처리와 같이 경우에 따라 SQL 구문 처리가 필요한 상황에서는 복잡하게 작성된다. (SQL 문이 길어지고 복잡해지면 저자는 XML로 처리하는 것이 더 알아보기 쉽고 관리하기도 쉽다고 생각한다고한다...)
1) org.zerock.mapper 패키지의 BoardMapper에는 위에서 작성한 Criteria 타입을 파라미터로 사용하는 getListWithPaging() 메서드를 작성한다.
2) 기존에 만들어둔 src/main/resources 의 BoardMapper.xml에 getListWithPaging에 해당하는 태그를 추가한다.
<select id="getListWithPaging" resultType="org.zerock.domain.BoardVO">
<![CDATA[
select
bno, title, content, writer, regdate, updatedate
from
(
select /*+INDEX_DESC(tbl_board pk_board) */
rownum rn, bno, title, content, writer, regdate, updatedate
from
tbl_board
where rownum <= 20
)
where rn > 10
]]>
</select>
작성된 BoardMapper.xml에서는 XML의 CDATA 처리가 들어간다. CDATA 섹션은 XML에서 사용할 수 없는 부등호를 사용하기 위함인데, XML을 사용할 경우에는 '<, >'는 태그로 인식하는데, 이로 인해 생기는 문제를 막기 위함이다. (< 나 >와 같은 특수 문자를 사용할 수도 있긴하다)
인라인뷰에서는 BoardVO를 구성하는데 필요한 모든 칼럼과 ROWNUM을 RN이라는 가명을 이용해서 만들어 주고 바깥쪽 SQL에서는 RN 칼럼을 조건으로 처리한다.
1-1. 페이징 테스트와 수정
MyBatis의 '#{}'를 적용하기 전에 XML 설정이 제대로 동작하는지 테스트를 먼저 진행하는 것이 좋다. 테스트 환경은 이미 준비되어 있으므로 간단히 테스트 코드만을 추가할 수 있다.
1) src/test/java 내에 있는 BoardMapperTests 클래스에 메서드를 추가한다.
@Test
public void testPaging() {
Criteria cri = new Criteria();
List<BoardVO> list = mapper.getListWithPaging(cri);
list.forEach(board -> log.info(board));
}
Criteria 클래스에서 생성된 객체는 pageNum은 1, amount 10 이라는 기본 값을 가지므로 별도의 파라미터 없이 생성한다. 현재는 파라미터의 값이 반영되지 않았으므로 2페이지의 내용이 정상적으로 나오는지 확인한다.
SQL에 문제가 없다는 것을 확인했다면 이제 Criteria 객체 내부의 값을 이용해서 SQL이 동작하도록 수정한다. 20과 10이라는 값은 결국 pageNum과 amount를 이용해서 조절되는 값이다.
2) BoardMapper.xml을 수정해서 페이지 번화와 데이터 수를 변경 할 수 있게 수정한다.
<select id="getListWithPaging" resultType="org.zerock.domain.BoardVO">
<![CDATA[
select
bno, title, content, writer, regdate, updatedate
from
(
select /*+INDEX_DESC(tbl_board pk_board) */
rownum rn, bno, title, content, writer, regdate, updatedate
from
tbl_board
where rownum <= #{pageNum} * #{amount}
)
where rn > (#{pageNum} -1) * #{amount}
]]>
</select>
3) 이전의 testPaging()을 조금 수정해서 확인하도록 한다.
확인을 위해서 Criteria 객체를 생성할 때 파라미터를 추가해보거나, setter를 이용해서 내용을 수정한다. 위의 경우는 한 페이지당 10개씩 출력하는 3페이지에 해당하는 데이터를 구한 것이다. 테스트 코드가 동작한 후에는 SQL Developer에서 실행된 결과와 동일한지 체크하고 페이지 번호를 변경해서 정상적으로 번호가 처리되는지 확인한다.
2. BoardController 와 BoardService 수정
페이징 처리는 브라우저에서 들어오는 정보들을 기준으로 동작하기 때문에 BoatdController와 BoardService 역시 전달되는 파라미터들을 받는 형태로 수정해야 한다.
2-1. BoardService 수정
1) BoardService는 Criteria를 파라미터로 처리하도록 BoardService 인터페이스와 BoardServiceImpl 클래스를 수정한다.
2) 동일 패키지 내에 BoardServiceImpl도 수정한다.
3) 테스트를 진행한다. BoardService 쪽에 대한 수정이 이루어 졌기때문에 테스트 코드 역시 에러가 발생하므로 다음과 같이 수정한다.
4) 기존 BoardController의 list()는 아무런 파라미터가 없이 처리되었기 때문에 pageNum과 amount를 처리하기 위해서 아래와 같이 수정한다.
Criteria 클래스를 하나 만들어 두면 위와 같이 편하게 하나의 타입만으로 파라미터나 리턴 타입을 사용할 수 있기 때문에 여러모로 편리하다! ㅎㅎ
5) BoardController 역시 이전에 테스트를 진행했으므로, pageNum 과 amount를 파라미터로 테스트한다.
@Test
public void testListPaging() throws Exception{
log.info(mockMvc.perform(
MockMvcRequestBuilders.get("/board/list")
.param("pageNum", "2")
.param("amount", "50"))
.andReturn().getModelAndView().getModelMap());
}
'Spring' 카테고리의 다른 글
[21] 기본적인 웹 게시물 관리 - 검색처리 (0) | 2019.12.26 |
---|---|
[20] 기본적인 웹 게시물 관리 - 페이징 화면 처리 (0) | 2019.12.25 |
[18] 기본적인 웹 게시물 관리 - 오라클 데이터베이스 페이징 처리 2 (0) | 2019.12.23 |
[17] 기본적인 웹 게시물 관리 - 오라클 데이터베이스 페이징 처리 (0) | 2019.12.23 |
[16] 기본적인 웹 게시물 관리 - 화면 처리 3 (0) | 2019.12.20 |