HomeBlogGuestbookLab 

JDM's Blog

온갖 테스트 결과가 기록되는 이곳은 JDM's Blog입니다. :3

SpringBoot JPA Pagination

JPA를 쓰는건 참 편리하고 좋은데, 페이징도 자동으로 해주면 참 좋겠죠? 간단하게 페이징을 할 수 있는 방법을 알아봅니다.

JPA Pagination

이번 포스팅은 아래의 포스트들을 기반으로 작성되었습니다.

미리 읽고 오시면 더욱 좋습니다. :D

Create Project

페이징 데모를 위해서 프로젝트를 생성합니다.

Name : pagination
Type : Gradle Project
Packaging : Jar
Java Version : 1.7
Language : Java
Boot Version : 1.2.4
Group : kr.jdm
Artifact : pagination
Version : 0.0.1-SNAPSHOT
Description : Demo project for Spring Boot
Package : jpa
Dependencies : H2, JPA

Example

이제 실제로 코드를 짜봅니다. 시나리오는 정해진 아이템 개수만큼 N번째 페이지에 있는 게시물 목록을 호출하는겁니다.

Entity

간단한 게시물 Entity입니다.

package pagination;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
public class BoardEntity {

	@Id
	@GeneratedValue(strategy=GenerationType.AUTO)
	private int seq; // 게시글 번호

	@Column
	private String author; // 게시글 작성자

	@Column
	private String subject; // 게시글 제목

	@Column
	private String content; // 게시글 본문

	public BoardEntity() {}

	public int getSeq() {
		return seq;
	}

	public void setSeq(int seq) {
		this.seq = seq;
	}

	public String getAuthor() {
		return author;
	}

	public void setAuthor(String author) {
		this.author = author;
	}

	public String getSubject() {
		return subject;
	}

	public void setSubject(String subject) {
		this.subject = subject;
	}

	public String getContent() {
		return content;
	}

	public void setContent(String content) {
		this.content = content;
	}
}

Repository

게시물 Repostiory입니다. @Query 메소드도 있고 Name 기반 메소드도 있습니다.

package pagination;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.data.repository.query.Param;

public interface BoardRepository extends PagingAndSortingRepository<BoardEntity, Integer> {
	Page<BoardEntity> findAll(Pageable pageable);
	Page<BoardEntity> findAllByOrderBySeqDesc(Pageable pageable);
	Page<BoardEntity> findAllByAuthor(String author, Pageable pageable);

	@Query("select t  from BoardEntity t where content like concat('%', :searchString ,'%')")
	Page<BoardEntity> findAllSearch(@Param("searchString") String searchString, Pageable pageable);

}

Application

실제로 구동 시키기 위한 코드입니다. 테스트 코드가 아닙니다. 테스트 코드는 Junit으로 작성합시다. :)

package pagination;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;

@SpringBootApplication
public class PaginationApplication implements CommandLineRunner {

	@Autowired
	private BoardRepository boardRepository;

   public static void main(String[] args) {
       SpringApplication.run(PaginationApplication.class, args);
   }

	@Override
	public void run(String... arg0) throws Exception {

		// 미리 아이템 100개를 적재
		for(int i = 0 ; i < 100; i++){
			BoardEntity be = new BoardEntity();
			be.setContent(dummyString());
			if( i % 3 == 0 ){
				be.setAuthor("first");
			}
			else if( i % 3 == 1 ) {
				be.setAuthor("second");
			}
			else {
				be.setAuthor("third");
			}
			boardRepository.save(be);
		}

		// 한 페이지 아이템 10개, 0번째 페이지 호출
		Page<BoardEntity> page = boardRepository.findAll(new PageRequest(0, 10));
		printPageData("simple", page);

		// 한 페이지 아이템 10개, 글번호 내림차순으로, 0번째 페이지 호출
		page = boardRepository.findAllByOrderBySeqDesc(new PageRequest(0, 10));
		printPageData("sort_seq_desc", page);

		// 한 페이지에 아이템 10개, 글번호 내림차순으로, 2번째 페이지 호출
		page = boardRepository.findAll(new PageRequest(2, 10, new Sort(Direction.DESC, "seq")));
		printPageData("sort", page);

		// 한페이지에 아이템 10개, 글작성자 "first", 0번째 페이지 호출
		page = boardRepository.findAllByAuthor("first", new PageRequest(0, 10));
		printPageData("sort_author", page);

		// 한페이지 아이템 10개, 작성자 내림차순으로, 2번째 페이지 호출
		page = boardRepository.findAll(new PageRequest(2, 10, new Sort(Direction.DESC, "author")));
		printPageData("sort_author_desc", page);

		// 한페이지 아이템 10개, 검색어 중, 글번호 내림차순으로, 2번째 페이지 호출
		page = boardRepository.findAllSearch("bc", new PageRequest(2, 10, new Sort(Direction.DESC, "seq")));
		printPageData("sort_search_desc", page);

	}

	// 페이지 데이터 출력
	private void printPageData(String label, Page<BoardEntity> page){
		if( page == null || page.getSize() <= 0 ) return;

		for( int i = 0 ; i < page.getSize(); i++ ){
			BoardEntity be = page.getContent().get(i);
			System.out.println("["+label+"] "+ be.getSeq() + " " + be.getAuthor() + " " + be.getContent());
		}
	}

	// 더미 문자열 반환
	private String dummyString(){

		String [] dummy = {"abc", "bcd", "cde", "def"};
		int rand = (int)(System.currentTimeMillis() % dummy.length);

		return dummy[rand];
	}
}

check result

결과 화면을 봅시다.

[simple] 1 first bcd
[simple] 2 second cde
[simple] 3 third def
[simple] 4 first def
[simple] 5 second cde
[simple] 6 third def
[simple] 7 first abc
[simple] 8 second abc
[simple] 9 third bcd
[simple] 10 first cde
[sort_seq_desc] 100 first cde
[sort_seq_desc] 99 third cde
[sort_seq_desc] 98 second bcd
[sort_seq_desc] 97 first bcd
[sort_seq_desc] 96 third abc
[sort_seq_desc] 95 second abc
[sort_seq_desc] 94 first def
[sort_seq_desc] 93 third def
[sort_seq_desc] 92 second cde
[sort_seq_desc] 91 first cde
[sort] 80 second abc
[sort] 79 first abc
[sort] 78 third def
[sort] 77 second def
[sort] 76 first cde
[sort] 75 third cde
[sort] 74 second bcd
[sort] 73 first bcd
[sort] 72 third abc
[sort] 71 second abc
[sort_author] 1 first bcd
[sort_author] 4 first def
[sort_author] 7 first abc
[sort_author] 10 first cde
[sort_author] 13 first abc
[sort_author] 16 first cde
[sort_author] 19 first abc
[sort_author] 22 first cde
[sort_author] 25 first abc
[sort_author] 28 first cde
[sort_author_desc] 69 third def
[sort_author_desc] 6 third def
[sort_author_desc] 12 third def
[sort_author_desc] 9 third bcd
[sort_author_desc] 99 third cde
[sort_author_desc] 72 third abc
[sort_author_desc] 3 third def
[sort_author_desc] 75 third cde
[sort_author_desc] 96 third abc
[sort_author_desc] 15 third bcd
[sort_search_desc] 58 first bcd
[sort_search_desc] 57 third bcd
[sort_search_desc] 56 second abc
[sort_search_desc] 55 first abc
[sort_search_desc] 50 second bcd
[sort_search_desc] 49 first bcd
[sort_search_desc] 48 third abc
[sort_search_desc] 47 second abc
[sort_search_desc] 42 third bcd
[sort_search_desc] 41 second bcd