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