๊ฒ์ ์กฐ๊ฑด : ๋์ด 10์ด
์ ๋ ฌ ์กฐ๊ฑด : ์ด๋ฆ์ผ๋ก ๋ด๋ฆผ์ฐจ์
ํ์ด์ง ์กฐ๊ฑด : ์ฒซ ๋ฒ์งธ ํ์ด์ง, ํ์ด์ง๋น ๋ณด์ฌ์ค ๋ฐ์ดํฐ๋ 3๊ฑด
์์ JPA
์ ํ์ด์ง๊ณผ ์ ๋ ฌ
์ ์ฌ์ฉํ๋ ์์ ์ฝ๋๋ฅผ ๋ณด์.// ์์ JPA ํ์ด์ง Repository ์ฝ๋
public List<Member> findByPage(int age, int offset, int limit) {
return em.createQuery("select m from Member m where m.age = :age order by m.username desc")
.setParameter("age", age)
.setFirstResult(offset)
.setMaxResults(limit)
.getResultList();
}
public long totalCount(int age) {
return em.createQuery("select count(m) from Member m where m.age = :age", Long.class)
.setParameter("age", age)
.getSingleResult();
}
// ์์ JPA ํ์ด์ง test ์ฝ๋
@Test
public void paging() throws Exception {
//given
memberJpaRepository.save(new Member("member1", 10));
memberJpaRepository.save(new Member("member2", 10));
memberJpaRepository.save(new Member("member3", 10));
memberJpaRepository.save(new Member("member4", 10));
memberJpaRepository.save(new Member("member5", 10));
int age = 10;
int offset = 0;
int limit = 3;
//when
List<Member> members = memberJpaRepository.findByPage(age, offset, limit);
long totalCount = memberJpaRepository.totalCount(age);
//then
assertThat(members.size()).isEqualTo(3);
assertThat(totalCount).isEqualTo(5);
}
org.springframework.data.domain.Sort
: ์ ๋ ฌ ๊ธฐ๋ฅ
org.springframework.data.domain.Pageable
: ํ์ด์ง ๊ธฐ๋ฅ (๋ด๋ถ์ Sort
ํฌํจ)
org.springframework.data.domain.Page
: ์ถ๊ฐ count ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ํฌํจํ๋ ํ์ด์ง
org.springframework.data.domain.Slice
: ์ถ๊ฐ count ์ฟผ๋ฆฌ ์์ด ๋ค์ ํ์ด์ง๋ง ํ์ธ ๊ฐ๋ฅ
List
(์๋ฐ ์ปฌ๋ ์
) : ์ถ๊ฐ count ์ฟผ๋ฆฌ ์์ด ๊ฒฐ๊ณผ๋ง ๋ฐํ
// ํ์ด์ง๊ณผ ์ ๋ ฌ ์ฌ์ฉ ์์
Page<Member> findByUsername(String name, Pageable pageable); // count ์ฟผ๋ฆฌ ์ฌ์ฉ
Slice<Member> findByUsername(String name, Pageable pageable); // count ์ฟผ๋ฆฌ ์ฌ์ฉ ์ํจ
List<Member> findByUsername(String name, Pageable pageable); // count ์ฟผ๋ฆฌ ์ฌ์ฉ ์ํจ
List<Member> findByUsername(String name, Sort sort);
๊ฒ์ ์กฐ๊ฑด : ๋์ด 10์ด
์ ๋ ฌ ์กฐ๊ฑด : ์ด๋ฆ์ผ๋ก ๋ด๋ฆผ์ฐจ์
ํ์ด์ง ์กฐ๊ฑด : ์ฒซ ๋ฒ์งธ ํ์ด์ง, ํ์ด์ง๋น ๋ณด์ฌ์ค ๋ฐ์ดํฐ๋ 3๊ฑด
Spring Data JPA
์ ํ์ด์ง๊ณผ ์ ๋ ฌ
์ ์ฌ์ฉํ๋ ์์ ์ฝ๋๋ฅผ ๋ณด์.// Page ์ฌ์ฉ ์์ ์ ์ ์ฝ๋
public interface MemberRepository extends Repository<Member, Long> {
Page<Member> findByAge(int age, Pageable pageable);
}
๋ ๋ฒ์งธ ํ๋ผ๋ฏธํฐ๋ก ๋ฐ์ Pagable์ ์ธํฐํ์ด์ค
๋ฐ๋ผ์ ์ค์ ์ฌ์ฉํ ๋๋ ํด๋น ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ org.springframework.data.domain.PageRequest
๊ฐ์ฒด๋ฅผ ์ฌ์ฉ
// Page ์ฌ์ฉ ์์ ์คํ ์ฝ๋
// ํ์ด์ง ์กฐ๊ฑด๊ณผ ์ ๋ ฌ ์กฐ๊ฑด ์ค์
@Test
public void page() throws Exception {
//given
memberRepository.save(new Member("member1", 10));
memberRepository.save(new Member("member2", 10));
memberRepository.save(new Member("member3", 10));
memberRepository.save(new Member("member4", 10));
memberRepository.save(new Member("member5", 10));
//when
PageRequest pageRequest = PageRequest.of(0, 3, Sort.by(Sort.Direction.DESC, "username"));
Page<Member> page = memberRepository.findByAge(10, pageRequest);
//then
List<Member> content = page.getContent(); // ์กฐํ๋ ๋ฐ์ดํฐ
assertThat(content.size()).isEqualTo(3); // ์กฐํ๋ ๋ฐ์ดํฐ ์
assertThat(page.getTotalElements()).isEqualTo(5); // ์ ์ฒด ๋ฐ์ดํฐ ์
assertThat(page.getNumber()).isEqualTo(0); // ํ์ด์ง ๋ฒํธ
assertThat(page.getTotalPages()).isEqualTo(2); // ์ ์ฒด ํ์ด์ง ๋ฒํธ
assertThat(page.isFirst()).isTrue(); // ์ฒซ๋ฒ์งธ ํญ๋ชฉ์ธ๊ฐ?
assertThat(page.hasNext()).isTrue(); // ๋ค์ ํ์ด์ง๊ฐ ์๋๊ฐ?
}
PageRequest
์์ฑ์์ ์ฒซ ๋ฒ์งธ ํ๋ผ๋ฏธํฐ์๋ ํ์ฌ ํ์ด์ง๋ฅผ, ๋ ๋ฒ์งธ ํ๋ผ๋ฏธํฐ์๋ ์กฐํํ ๋ฐ์ดํฐ ์๋ฅผ ์
๋ ฅ
์ฌ๊ธฐ์ ์ถ๊ฐ๋ก ์ ๋ ฌ ์ ๋ณด๋ ํ๋ผ๋ฏธํฐ๋ก ์ฌ์ฉํ ์ ์๋ค.
โ Page๋ 1๋ถํฐ ์์์ด ์๋๋ผ 0๋ถํฐ ์์
// Page ์ธํฐํ์ด์ค
public interface Page<T> extends Slice<T> {
int getTotalPages(); // ์ ์ฒด ํ์ด์ง ์
long getTotalElements(); // ์ ์ฒด ๋ฐ์ดํฐ ์
<U> Page<U> map(Function<? super T, ? extends U> converter); // ๋ณํ๊ธฐ
}
// Slice ์ธํฐํ์ด์ค
public interface Slice<T> extends Streamable<T> {
int getNumber(); // ํ์ฌ ํ์ด์ง
int getSize(); // ํ์ด์ง ํฌ๊ธฐ
int getNumberOfElements(); // ํ์ฌ ํ์ด์ง์ ๋์ฌ ๋ฐ์ดํฐ ์
List<T> getContent(); // ์กฐํ๋ ๋ฐ์ดํฐ
boolean hasContent(); // ์กฐํ๋ ๋ฐ์ดํฐ ์กด์ฌ ์ฌ๋ถ
Sort getSort(); // ์ ๋ ฌ ์ ๋ณด
boolean isFirst(); // ํ์ฌ ํ์ด์ง๊ฐ ์ฒซ ํ์ด์ง ์ธ์ง ์ฌ๋ถ
boolean isLast(); // ํ์ฌ ํ์ด์ง๊ฐ ๋ง์ง๋ง ํ์ด์ง ์ธ์ง ์ฌ๋ถ
boolean hasNext(); // ๋ค์ ํ์ด์ง ์ฌ๋ถ
boolean hasPrevious(); // ์ด์ ํ์ด์ง ์ฌ๋ถ
Pageable getPageable(); // ํ์ด์ง ์์ฒญ ์ ๋ณด
Pageable nextPageable(); // ๋ค์ ํ์ด์ง ๊ฐ์ฒด
Pageable previousPageable();// ์ด์ ํ์ด์ง ๊ฐ์ฒด
<U> Slice<U> map(Function<? super T, ? extends U> converter); // ๋ณํ๊ธฐ
}
// count ์ฟผ๋ฆฌ๋ฅผ ๋ค์๊ณผ ๊ฐ์ด ๋ถ๋ฆฌํ ์ ์๋ค.
@Query(value = โselect m from Member mโ, countQuery = โselect count(m.username) from Member mโ)
Page<Member> findMemberAllCountBy(Pageable pageable);
์นด์ดํธ ์ฟผ๋ฆฌ ๋ถ๋ฆฌ
(๋ณต์กํ sql์์ ์ฌ์ฉ, ๋ฐ์ดํฐ๋ left join, ์นด์ดํธ๋ left join ์ ํด๋ ๋จ)
Page<Member> page = memberRepository.findByAge(10, pageRequest);
Page<MemberDto> dtoPage = page.map(m -> new MemberDto());