#14 simple blog : pageable - querydsl

This commit is contained in:
haerong22
2022-07-27 03:34:50 +09:00
parent 929877b099
commit 373a656349
10 changed files with 132 additions and 14 deletions

View File

@@ -23,6 +23,13 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'com.querydsl:querydsl-core'
implementation 'com.querydsl:querydsl-jpa'
annotationProcessor("com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jpa")
annotationProcessor("jakarta.persistence:jakarta.persistence-api")
annotationProcessor("jakarta.annotation:jakarta.annotation-api")
compileOnly 'org.projectlombok:lombok'
runtimeOnly 'com.h2database:h2'
annotationProcessor 'org.projectlombok:lombok'

View File

@@ -0,0 +1,20 @@
package com.example.simpleblog.config;
import com.querydsl.jpa.impl.JPAQueryFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
@Configuration
public class QueryDslConfig {
@PersistenceContext
public EntityManager em;
@Bean
public JPAQueryFactory jpaQueryFactory() {
return new JPAQueryFactory(em);
}
}

View File

@@ -1,12 +1,11 @@
package com.example.simpleblog.controller;
import com.example.simpleblog.request.PostCreate;
import com.example.simpleblog.request.PostSearch;
import com.example.simpleblog.response.PostResponse;
import com.example.simpleblog.service.PostService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableDefault;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
@@ -30,7 +29,7 @@ public class PostController {
}
@GetMapping("/posts")
public List<PostResponse> getPostList(@PageableDefault Pageable pageable) {
return postService.getPostList(pageable);
public List<PostResponse> getPostList(PostSearch postSearch) {
return postService.getPostList(postSearch);
}
}

View File

@@ -3,5 +3,5 @@ package com.example.simpleblog.repository;
import com.example.simpleblog.domain.Post;
import org.springframework.data.jpa.repository.JpaRepository;
public interface PostRepository extends JpaRepository<Post, Long> {
public interface PostRepository extends JpaRepository<Post, Long>, PostRepositoryCustom {
}

View File

@@ -0,0 +1,11 @@
package com.example.simpleblog.repository;
import com.example.simpleblog.domain.Post;
import com.example.simpleblog.request.PostSearch;
import java.util.List;
public interface PostRepositoryCustom {
List<Post> getList(PostSearch postSearch);
}

View File

@@ -0,0 +1,27 @@
package com.example.simpleblog.repository;
import com.example.simpleblog.domain.Post;
import com.example.simpleblog.request.PostSearch;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;
import java.util.List;
import static com.example.simpleblog.domain.QPost.post;
@Repository
@RequiredArgsConstructor
public class PostRepositoryImpl implements PostRepositoryCustom {
private final JPAQueryFactory jpaQueryFactory;
@Override
public List<Post> getList(PostSearch postSearch) {
return jpaQueryFactory.selectFrom(post)
.limit(postSearch.getSize())
.offset(postSearch.getOffset())
.orderBy(post.id.desc())
.fetch();
}
}

View File

@@ -0,0 +1,24 @@
package com.example.simpleblog.request;
import lombok.Builder;
import lombok.Data;
import static java.lang.Math.*;
@Data
@Builder
public class PostSearch {
private final int MAX_SIZE = 2000;
@Builder.Default
private Integer page = 1;
@Builder.Default
private Integer size = 10;
public long getOffset() {
return (long) (max(1, page) - 1) * min(size, MAX_SIZE);
}
}

View File

@@ -3,10 +3,10 @@ package com.example.simpleblog.service;
import com.example.simpleblog.domain.Post;
import com.example.simpleblog.repository.PostRepository;
import com.example.simpleblog.request.PostCreate;
import com.example.simpleblog.request.PostSearch;
import com.example.simpleblog.response.PostResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import java.util.List;
@@ -40,9 +40,9 @@ public class PostService {
.build();
}
public List<PostResponse> getPostList(Pageable pageable) {
public List<PostResponse> getPostList(PostSearch postSearch) {
// Pageable pageable = PageRequest.of(page, 5, Sort.Direction.DESC, "id");
return postRepository.findAll(pageable).stream()
return postRepository.getList(postSearch).stream()
.map(PostResponse::new)
.collect(Collectors.toList());
}

View File

@@ -155,11 +155,39 @@ class PostControllerTest {
postRepository.saveAll(requestPosts);
// expected
mockMvc.perform(get("/posts?page=1&size=5&sort=id,desc")
mockMvc.perform(get("/posts?page=1&size=10")
.contentType(APPLICATION_JSON)
)
.andExpect(status().isOk())
.andExpect(jsonPath("$.length()", is(5)))
.andExpect(jsonPath("$.length()", is(10)))
.andExpect(jsonPath("$[0].id").value("30"))
.andExpect(jsonPath("$[0].title").value("제목 30"))
.andExpect(jsonPath("$[0].content").value("내용 30"))
.andDo(print())
;
}
@Test
@DisplayName("페이지를 0으로 요청하면 첫 페이지를 가져온다.")
void get_post_list_page_0() throws Exception {
// given
List<Post> requestPosts = IntStream.range(1, 31)
.mapToObj(i -> Post.builder()
.title("제목 " + i)
.content("내용 " + i)
.build()
)
.collect(Collectors.toList());
postRepository.saveAll(requestPosts);
// expected
mockMvc.perform(get("/posts?page=0&size=10")
.contentType(APPLICATION_JSON)
)
.andExpect(status().isOk())
.andExpect(jsonPath("$.length()", is(10)))
.andExpect(jsonPath("$[0].id").value("30"))
.andExpect(jsonPath("$[0].title").value("제목 30"))
.andExpect(jsonPath("$[0].content").value("내용 30"))

View File

@@ -3,13 +3,13 @@ package com.example.simpleblog.service;
import com.example.simpleblog.domain.Post;
import com.example.simpleblog.repository.PostRepository;
import com.example.simpleblog.request.PostCreate;
import com.example.simpleblog.request.PostSearch;
import com.example.simpleblog.response.PostResponse;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.PageRequest;
import java.util.List;
import java.util.stream.Collectors;
@@ -17,7 +17,6 @@ import java.util.stream.IntStream;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.springframework.data.domain.Sort.Direction.DESC;
@SpringBootTest
class PostServiceTest {
@@ -87,11 +86,14 @@ class PostServiceTest {
// when
List<PostResponse> posts = postService.getPostList(
PageRequest.of(0, 5, DESC, "id")
PostSearch.builder()
.page(1)
.size(10)
.build()
);
// then
assertEquals(5L, posts.size());
assertEquals(10L, posts.size());
assertEquals("제목 30", posts.get(0).getTitle());
assertEquals("내용 30", posts.get(0).getContent());
assertEquals("제목 26", posts.get(4).getTitle());