#14 simple blog : pageable - querydsl
This commit is contained in:
@@ -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'
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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"))
|
||||
|
||||
@@ -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());
|
||||
|
||||
Reference in New Issue
Block a user