3 minute read

paging

  • paginInfo 파일 추가
    • @param currentPage 현재 페이지
    • @param pageLimit 보여지는 paing의 개수
      • < 1 2 3 4 5 > : 여기서는 5개
    • @param listCount 전체 게시글의 개수
    • @param listLimit 한 페이지에 표시될 게시글의 개수
  • paging 처리를 위해 전체 게시글 개수부터 가져오기

Alt text

servlet/JSP 수업 때 사용했던 파일을 그대로 사용했다.


test 코드 작성

  • 필터 기능을 통해 조회되는 게시글만 조회
    • listCount(전체 게시글의 개수)를 필터가 적용된 수로 가져오기.ㅠㅠ
    • getBoardCount() 메서드를 필터링 된 것으로 가져오기.
@Test
public void getBoardCountTest() {
	int count = 0;
	// 필터 사용
	String[] filters = new String[] {"B2", "B3"};

	// 필터 넘겨주기
	count = service.getBoardCount(filters);

	assertThat(count).isGreaterThan(0);
}

service 코드 작성

public int getBoardCount(String[] filters) {
	int count = 0;
	SqlSession session = getSession();
	
	// Arrays.asList(filters) : List로 넘기기
	count = dao.findBoardCount(session, Arrays.asList(filters));
	
	session.close();
	
	return count;
}

dao 코드 작성

// List<String> : 리스트로 넘겨기
public int findBoardCount(SqlSession session, List<String> filters) {

	// 총 게시글의 개수를 조회하기 때문에 selectOne() 사용
	return session.selectOne("boardMapper.getBoardCountByFilters", filters);
}

service / dao에서 list로 넘겼기 때문에 쿼리문에서도 list로 작성해야한다!


쿼리문 작성

<select id="getBoardCountByFilters" parameterType="map" resultType="_int">
	<!-- sql 조각은 모든 컬럼을 조회하기 때문에 사용하지 않고 따로 작성 -->
	SELECT COUNT(*)
	FROM BOARD
	WHERE STATUS = 'Y'
	
	<!-- list로 작성하기. filters라는 이름으로 사용하고 싶을 경우 dao에서 map으로 만들어서 넘기기 -->
	<if test="list != null">
		AND TYPE IN 
		<foreach collection="list" item="filter" open="(" separator="," close=")">
			#{ filter }
		</foreach>
	</if>
</select>

매개값 주입 받기

  • @MethodSource : 외부/내부에서 반환되는 값을 매개값으로 사용
  • 지금 생성한 메서드의 리턴값을 getBoardcountTest()에서 사용할 예정

@MethodeSource에 사용될 메서드 생성 * static 메서드여야 함 * stream을 반환 함

public static Stream<Arguments> filterProvider() {
	return Stream.of(
		Arguments.arguments((Object) new String[] {"B2", "B3"}),
		Arguments.arguments((Object) new String[] {"B1"})
	);
}

-

@ParameterizedTest
@MethodSource("filterProvider") // filterProvider() 메서드의 리턴값을 해당 Test에서 사용
@DisplayName("조회되는 게시글 개수 - 필터 기능 포함")
public void getBoardCountTest(String[] filters) {
	int count = 0;
	// 계속 이런식으로 주석 처리 했다 풀었다 하면서 테스트 진행했었음
	// String[] filters = new String[] {"B1"};
	// String[] filters = new String[] {"B2", "B3"};
	
	count = service.getBoardCount(filters);
	
	System.out.println(count);
	
	assertThat(count).isPositive().isGreaterThan(0);
}

Alt text

앞에서는 타입별로(B1, B2, B3) 매개값을 바꿔주면서 테스트를 진행했다.
MethodeSource를 사용하니 그럴 필요 없이 테스트가 가능하게 됐다.
테스트 코드의 매개값을 수정없이 테스트할 수 있게 되어 편한 기능인 거 같다. 하지만 어렵다.^^


paging - test 코드 작성

  • findAllTest() 메서드에 추가 작성
  • 기존방식 : 쿼리문 작성하여 처리
    • 단점 : 검색해하는 조건이 변경될 경우 쿼리문 수정 필요
@ParameterizedTest
@MethodSource("filterProvider")
@DisplayName("게시글 목록 조회 - 필터 기능 포함")
public void findAllTest(String[] filters) {
	List<Board> list = null;
	PageInfo pageInfo = null; // pageInfo 객체 생성
	int listCount = 0;
	
	listCount = service.getBoardCount(filters);

	pageInfo = new PageInfo(5, 10, listCount, 10);
	// 현재 페이지, paging 개수, 전체 게시글 개수, 한 페이지의 최대 게시글 개수

	// service에 요청할 pageInfo 추가
	list = service.findAll(filters, pageInfo);
	
	System.out.println(list);
	System.out.println(list.size());
	
	assertThat(list).isNotNull();
	assertThat(list.size()).isPositive().isEqualTo(expected);
}

paging - service 코드 작성

  • findAll() 메서드에 pageInfo 매개값 추가
public List<Board> findAll(String[] filters, PageInfo pageInfo) {
	List<Board> list = null;
	SqlSession session = getSession();
	
	// dao에도 pageInfo 추가
	list = dao.findAll(session, filters, pageInfo);
	
	session.close();
	
	return list;
}

paging - dao 코드 작성

  • mybatis에서 제공하는 RowBounds 클래스 사용
    • 쿼리문 수정없이 쿼리문 실행 후, 조회가 되면 RowBounds를 갖고 원하는 데이터만 추출
    • RowBounds 객체 생성 시 offset / limit 값을 전달하여 paging 구현
      • offset = 0, limit = 10으로 세팅 시
        • 0개를 건너뛰고 10개를 가져온다.(1번-10번)
      • offset = 10, limit = 10으로 세팅 시
        • 10개를 건너뛰고 10개를 가져온다.(11번-10번)
      • offset = 20, limit = 10으로 세팅 시
        • 20개를 건너뛰고 10개를 가져온다.(21번-10번)
  • servlet/JSP 방식 : rownum, subQuery를 사용한 쿼리문 작성하여 조회
public List<Board> findAll(SqlSession session, String[] filters, PageInfo pageInfo) {
	// map 객체에 담아서 넘기기
	Map<String, Object> map = new HashMap<>();
	map.put("filters", filters);
	
	// (pageInfo에서 현재 페이지 -1) * (페이지 인포에서 한 페이지에 보여질 최대 게시글 개수)
	// 현재 페이지가 1페이지일 경우 offset이 0이어야되기 때문에 -1
	// 그리고 10을 곱하면 0
	int offset = (pageInfo.getCurrentPage() -1 ) * pageInfo.getListLimit();
	int limit = pageInfo.getListLimit();
	RowBounds rowBounds = new RowBounds(offset, limit);
	
	return session.selectList("boardMapper.selectBoardListByFilters", map, rowBounds);
}

필터 / 현재 페이지를 받는 메서드 생성

@ParameterizedTest
@MethodSource("listProvider")
@DisplayName("게시글 목록 조회  -필터 기능 포함")
public void findAllTest(String[] filters) {
	List<Board> list = null;
	PageInfo pageInfo = null;
	int listCount = 0;

	listCount = service.getBoardCount(filters, int currentPage, int expected);
	pageInfo = new PageInfo(currentPage, 10, listCount, 10);
	list = service.findAll(filters, pageInfo);
	
	System.out.println(list.size());
	System.out.println(list);
	
	assertThat(list).isNotNull();
	// expected : listProvider() 메서드에서 3번째 매개값으로 작성한 값
	assertThat(list.size()).isPositive().isEqualTo(expected);
}

// 다른 메서드에서 매개값으로 사용할 메서드 생성
public static Stream<Arguments> listProvider() {
	return Stream.of(
		// {"type"}, 현재 페이지, 게시글 개수
		Arguments.arguments((Object) new String[] {"B2", "B3"}, 1, 4), // B2, B3 조회 시 1페이지에 게시글은 4개
		Arguments.arguments((Object) new String[] {"B1"}, 1, 10), 	   // B1 조회시 1페이지에는 10개의 게시글
		Arguments.arguments((Object) new String[] {"B1"}, 16, 4) 	   // B1 조회 시 16페이지에는 4개의 게시글
	);
}

Categories:

Updated: