Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package com.pinback.pinback_server.domain.article.application;

import java.util.List;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

Expand All @@ -8,7 +12,9 @@
import com.pinback.pinback_server.domain.article.domain.service.ArticleGetService;
import com.pinback.pinback_server.domain.article.domain.service.ArticleSaveService;
import com.pinback.pinback_server.domain.article.exception.ArticleAlreadyExistException;
import com.pinback.pinback_server.domain.article.presentation.dto.response.ArticleAllResponse;
import com.pinback.pinback_server.domain.article.presentation.dto.response.ArticleDetailResponse;
import com.pinback.pinback_server.domain.article.presentation.dto.response.ArticlesResponse;
import com.pinback.pinback_server.domain.category.domain.entity.Category;
import com.pinback.pinback_server.domain.category.domain.service.CategoryGetService;
import com.pinback.pinback_server.domain.user.domain.entity.User;
Expand Down Expand Up @@ -39,4 +45,17 @@ public ArticleDetailResponse getArticleDetail(long articleId) {
Article article = articleGetService.findById(articleId);
return ArticleDetailResponse.from(article);
}

public ArticleAllResponse getAllArticles(User user, int pageNumber, int pageSize) {
Page<Article> articles = articleGetService.findAll(user.getId(), PageRequest.of(pageNumber, pageSize));

List<ArticlesResponse> articlesResponses = articles.stream()
.map(ArticlesResponse::from)
.toList();

return ArticleAllResponse.of(
articles.getTotalElements(),
articlesResponses
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import com.pinback.pinback_server.domain.user.domain.entity.User;

@Repository
public interface ArticleRepository extends JpaRepository<Article, Long> {
public interface ArticleRepository extends JpaRepository<Article, Long>, ArticleRepositoryCustom {

boolean existsByUserAndUrl(User user, String url);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.pinback.pinback_server.domain.article.domain.repository;

import java.util.UUID;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

import com.pinback.pinback_server.domain.article.domain.entity.Article;

public interface ArticleRepositoryCustom {
Page<Article> findAllCustom(UUID userId, Pageable pageable);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.pinback.pinback_server.domain.article.domain.repository;

import static com.pinback.pinback_server.domain.article.domain.entity.QArticle.*;
import static com.pinback.pinback_server.domain.user.domain.entity.QUser.*;

import java.util.List;
import java.util.UUID;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.support.PageableExecutionUtils;
import org.springframework.stereotype.Repository;

import com.pinback.pinback_server.domain.article.domain.entity.Article;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;

import lombok.RequiredArgsConstructor;

@Repository
@RequiredArgsConstructor
public class ArticleRepositoryCustomImpl implements ArticleRepositoryCustom {

private final JPAQueryFactory queryFactory;

@Override
public Page<Article> findAllCustom(UUID userId, Pageable pageable) {
List<Article> articles = queryFactory
.selectFrom(article)
.join(article.user, user).fetchJoin()
.where(article.user.id.eq(userId))
.offset(pageable.getOffset())
.limit(pageable.getPageSize())
.orderBy(article.createdAt.desc())
.fetch();
Comment on lines +27 to +35
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

지금 구현하신 페이지네이션 방식은 offset 기반 외에도 cursor 기반이 있으니 시간이 될 때 공부하면 좋을 것 같습니당 💪💪💪


JPAQuery<Long> countQuery = queryFactory
.select(article.count())
.from(article)
.where(article.user.id.eq(userId));

return PageableExecutionUtils.getPage(articles, pageable, countQuery::fetchOne);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package com.pinback.pinback_server.domain.article.domain.service;

import java.util.UUID;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

Expand All @@ -23,4 +27,8 @@ public boolean checkExistsByUserAndUrl(User user, String url) {
public Article findById(long articleId) {
return articleRepository.findById(articleId).orElseThrow(ArticleNotFoundException::new);
}

public Page<Article> findAll(UUID userId, PageRequest pageRequest) {
return articleRepository.findAllCustom(userId, pageRequest);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.pinback.pinback_server.domain.article.application.ArticleManagementUsecase;
import com.pinback.pinback_server.domain.article.presentation.dto.request.ArticleCreateRequest;
import com.pinback.pinback_server.domain.article.presentation.dto.response.ArticleAllResponse;
import com.pinback.pinback_server.domain.article.presentation.dto.response.ArticleDetailResponse;
import com.pinback.pinback_server.domain.user.domain.entity.User;
import com.pinback.pinback_server.global.common.annotation.CurrentUser;
Expand All @@ -35,4 +37,12 @@ public ResponseDto<ArticleDetailResponse> getArticleDetails(@PathVariable Long a
return ResponseDto.ok(response);
}

@GetMapping
public ResponseDto<ArticleAllResponse> getAll(@CurrentUser User user, @RequestParam int pageNumber,
@RequestParam int pageSize) {

ArticleAllResponse response = articleManagementUsecase.getAllArticles(user, pageNumber, pageSize);
return ResponseDto.ok(response);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.pinback.pinback_server.domain.article.presentation.dto.response;

import java.util.List;

public record ArticleAllResponse(
long totalArticle,
List<ArticlesResponse> articles
) {
public static ArticleAllResponse of(long totalArticle, List<ArticlesResponse> articles) {
return new ArticleAllResponse(
totalArticle,
articles
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.pinback.pinback_server.domain.article.presentation.dto.response;

import com.pinback.pinback_server.domain.article.domain.entity.Article;

public record ArticlesResponse(
long articleId,
String url,
String memo,
boolean isRead
) {
public static ArticlesResponse from(Article article) {
return new ArticlesResponse(
article.getId(),
article.getUrl(),
article.getMemo(),
article.isRead()
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ public OpenAPI openAPI() {
.description("Pinback 서비스 API 문서")
.version("v1.0.0"))
.servers(List.of(
new Server().url("https://54.180.92.66.nip.io").description("배포 서버")))
new Server().url("https://54.180.92.66.nip.io").description("배포 서버"),
new Server().url("http://localhost:8080").description("로컬 서버")
))
.addSecurityItem(new SecurityRequirement().addList("Bearer Authentication"))
.components(new Components()
.addSecuritySchemes("Bearer Authentication",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import static org.assertj.core.api.Assertions.*;

import java.time.LocalDateTime;
import java.util.Comparator;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
Expand All @@ -17,7 +18,9 @@
import com.pinback.pinback_server.domain.article.domain.entity.Article;
import com.pinback.pinback_server.domain.article.domain.repository.ArticleRepository;
import com.pinback.pinback_server.domain.article.exception.ArticleAlreadyExistException;
import com.pinback.pinback_server.domain.article.presentation.dto.response.ArticleAllResponse;
import com.pinback.pinback_server.domain.article.presentation.dto.response.ArticleDetailResponse;
import com.pinback.pinback_server.domain.article.presentation.dto.response.ArticlesResponse;
import com.pinback.pinback_server.domain.category.domain.entity.Category;
import com.pinback.pinback_server.domain.category.domain.repository.CategoryRepository;
import com.pinback.pinback_server.domain.user.domain.entity.User;
Expand Down Expand Up @@ -91,4 +94,51 @@ void getArticleDetail() {
assertThat(response.remindAt()).isEqualTo(article.getRemindAt());
}

@DisplayName("사용자가 원하는 만큼 게시글 만큼 조회할 수 있다.")
@Test
void getAllArticle() {
//given
User user = userRepository.save(user());
User user2 = userRepository.save(userWithEmail("test2"));
Category category = categoryRepository.save(category(user));
Category category2 = categoryRepository.save(category(user2));

for (int i = 0; i < 12; i++) {
articleRepository.save(article(user, Integer.toString(i), category));
}

for (int i = 0; i < 12; i++) {
articleRepository.save(article(user2, Integer.toString(i), category2));
}

//when
ArticleAllResponse responses = articleManagementUsecase.getAllArticles(user, 0, 5);

//then
assertThat(responses.articles()).hasSize(5);
assertThat(responses.totalArticle()).isEqualTo(12);

}

@DisplayName("게시글이 최신순으로 조회된다.")
@Test
void getAllArticleOrderByCreatedAtDesc() {
//given
User user = userRepository.save(user());
Category category = categoryRepository.save(category(user));

for (int i = 0; i < 10; i++) {
articleRepository.save(article(user, "article" + i, category));
}

//when
ArticleAllResponse responses = articleManagementUsecase.getAllArticles(user, 0, 5);

//then
assertThat(responses.articles())
.hasSize(5)
.extracting(ArticlesResponse::articleId)
.isSortedAccordingTo(Comparator.reverseOrder());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,8 @@ public static Article article(User user) {
public static Article articleWithCategory(User user, Category category) {
return Article.create("test", "testmemo", user, category, LocalDateTime.of(2025, 7, 7, 12, 0, 0));
}

public static Article article(User user, String url, Category category) {
return Article.create(url, "testmemo", user, category, LocalDateTime.of(2025, 7, 7, 12, 0, 0));
}
}